From 21b315ceacef09046fd9a0329f385745da39be86 Mon Sep 17 00:00:00 2001 From: Tyler Hawkes Date: Tue, 9 Jun 2026 17:15:52 -0600 Subject: [PATCH] feat(xmtp_proto): XIP-83 Subscribe protos (bidi mutable subscription + ping/pong + TopicsLive) Co-Authored-By: Claude Fable 5 --- crates/xmtp_proto/proto_version | 2 +- .../xmtp_proto/src/gen/proto_descriptor.bin | Bin 366557 -> 375377 bytes crates/xmtp_proto/src/gen/xmtp.mls.api.v1.rs | 401 +++++ .../src/gen/xmtp.mls.api.v1.serde.rs | 1466 +++++++++++++++++ 4 files changed, 1868 insertions(+), 1 deletion(-) diff --git a/crates/xmtp_proto/proto_version b/crates/xmtp_proto/proto_version index aba460fee9..2a9c9a3a9b 100644 --- a/crates/xmtp_proto/proto_version +++ b/crates/xmtp_proto/proto_version @@ -1 +1 @@ -e6f640a8994dad1779da0280b15be482c0bb4bb8 +ac2aa57f7482e354b1903f562203169eb1cc479f diff --git a/crates/xmtp_proto/src/gen/proto_descriptor.bin b/crates/xmtp_proto/src/gen/proto_descriptor.bin index b2d195784bea23cf150880f12493ce6d28d40b3b..7fa0feea0e74d8c7bdb06de370279051dfb6b921 100644 GIT binary patch delta 39383 zcmaK#d4Lqvwg2ZYnsKhm>NuI`-0S1@|GlUsb^d+s} zhJvW07N}8hi6)YuqIOVm1=kQa+yFHqViXsQqJj&*&$&xillR__f0*y7d(S=h+;h%7 zcd6<(mvw*fi|)mBOV#MZi*sJ^{#z}NM)f>2cx+7&#ZTX%`Y%7S@MdRqd&hvw?^wS6 z@=nV8OSa>~1ryZ%9mii$zkL5I`-N)B@{{A+e0A;eZ?5a1mLGV-gl?3-{_YExA9&BX zDtdIYAEk4tJu5C>{?PJuSv7HaymGc5{Vobp6<(P0PwBY!v2zQd;xDgTR28L!?16gr ziYj%Xbk0B3tFw>N6g;(5FipWzO9eAI|Ce69EtsL;FTGw4QSg_2`dg0KoPS!WV3vYM zoK`BCrQ~U)l2Ok8RjFh|$zPQUMil%N1^=eBl$AMuLdUC*-=D9f)C8}SZMc$B6Kd+B z;gJ`pTxxPfN5|49hIgKv=^Y&$1%dJ^a{iQ#51%;XpebG?b%d0HR@ucN_)W=mcgP3z zs*Cp0m3h?MaoVaO2Q`-}D=IgaDk~|G(^`PBqH=SezR`ZVGLlX0cx=@H2Td(i_NY9y zRN15Q)Lb9ivPb2q{qoUIb!9+H$FS8W9@J8*>{Gd=vc?wosoc^YcO=SB4N(WiJPn zz`DI0^aT!Wh_-uLj;dTRZ+ZCaxoYIRghf>fs$x_P$0}INQ@NfF!eXB4-8Y(TSaiw- zS1o_|xj>D)Dq+zHDXvnLIa{X_EUr?ubq>PfD%H1NG#Kafa^bbAVnxT!zYi*0t1>-M zUl4e>XAmo|x2^#SG&G$AB4O+#1j0U6xT**Ygng{=Rl|vgiQk@gNyR5z5O2*C|HdwBx}F=vWa{ftD3z;dGtC0Bm76U8k@B!wGbQ z^7gh5eK-LNj+GCq8x*c#>f+MC-g`QzD-YhwvZC%E6y9OV1_nA#0i6Dz@DKYGPJd81 zh=p+agW7vY)LFXc52(n6H!1H{<(uceC>H1M8TE-mo>$1IEbjQ-i#>nBpER^s1yxaX zls3;8l*Ou3E+J5Rv8wHv5NK|(>fNWrjsi*K6$~pCkO6{_h$usJi|SOLlz`_gYWKok2?eINh=-VQLWtXv5l_Jo z=#-m+-EGd-Jdf}PtaBqy`~#LooU*qoZs>-t+xX*m5!?J*!)Dj~$fvckVIKi%E&*b8@d`KyY0 z*s+oMF<8b>?>2f_qCq`H2FsFBfdKzy$sj|Zg=NVg!#o$<#USrixT~Cz4DVg#jAVH4 zN`_ZYnh;8EoXG|EC~t`E2jN?w>ooBjSZQLE=aGW|dku7j5$PV)ndxMX?zNZA1^0Da z`qG6zx-VgoMWFkVm_l{}%$dO8dBksE{T|UM9SEXa@Hd3%sQK#9UwOnq4V^GVaGqAW z*hL5j_Hn~S3eaqCBv_o{VkFr^<+QMc%590w>ZJ=Sr}+G9sQ z=7va9(a2+Nh%|wEkEz;T+F3M#b{FWB9$~Tt(dVOLC zGJmaCqze+zDI#T5k9r4bc)c26OpmAd(0Vm+j1HIry9gdMIvT0@)7)Fi+oNt+oIgPg z>o|5@<&VI|s(nvl=Ub|>n`JH1yrsIEiG`=M^p@(sd-P*r6<~4iDDSyra@R zaT_cx(3bXY$NTHXobs*;s!i90O4IMET&)od0?aq5z#5ETL$Jyc0yQ?NF1hG(qZ=IQ zL*;Ezht&PP0M z!tEB-rMK0ZFIwB8`W_seA}-6|f1={Qo~C}*@%)BV!zZef2||8K#uI4LC?FDlqPq2r z_QmgmT=;KQv97~=bD!b=R+&E9Q3Fxi=gRBw%=`<6#pfzr8J&pwfa0iMc1(QpeEzMf9cdG1gd@I)Tgl_81-oaHNFz{on;w=cXV`mYt~6SRFD*tglC5olNna(p{Q?E z&{Yqd#xRCpMp6@~@r{V$7~?bF!+31R?r#q-d|%F-%rE%9oH?r8se*1L<}#l`s7VOa z*r{r}mc(IH&-2P^$g~L|slkF4f~zr=9x#~alNXeD%KQkSQ$nE1`Cd(zQX^QyY_F`( zGPyuV`kbN0Y>z%a=~*@5;Fm1_;XjX3^_O^M>ST!Oh9z1nWk?zR|t{=AOu?+hr+E9b@vH<%~f+~APR&o9@8B<>IrL93`S-^(TXBX_^t zvu-A%CwV%AL>Zl^ak*Dx4WK}g&beTL7xXBpt20#~m^dmtI#XqV*R^{|tm<5FMR|>C zYCuS8R8!*$sWH&@wFj1<(mODGAUFeqK#he`>O z*FPZK2x!6?5Lda$vnwtbdm)=qF*B0}9D0h`P-7pU7h zDmULa^0tJ9gz4M7%4*xXgz4M7nywB~=QgiL&!{LX&p?`Ax_tBIgVmu+6BaTXFHKY< zbMaCyXL2#Bz+$PlTfgY{ngeC;>NxdZ=Z(B8VZfF~a96@Wg3w(aley84B=vWBOyyS^ z84&pX3+|ql7Yw82C#nj=mMh&BGLmLQ$D9_`qB%eRF`6Al?TJetTLLF>^(4;eT->g^^QJ)%kC z)#IMGhwUS~8Uo$8vaJEEbS5E*@#9`klNeJKPLE4(?#f0P;YCb)WBFe{x+fUiZ%c0nB59Zl-}Nfa z>lpv1NMvH-O*-beu%e z&0gj1de90y)}{9_ISmk2n?1Yw3?;by%VWn$tQZ6sBx7t(TCL6HR>P1${gE zZtHQB=mB8X;`$+)_{_801)4y!pLuq>Koe;AGtX`p2!R6s?x@?g+o*q+Gm;4Q?{Y?> ziGO=`qd?b#(Z5Ble-?iUCH8#XaqhOIhkl*tKtj*gp3M*`0*|k~zGj04C{?_MVbN60 zfWCa&G2zRWk>4f^B=CHjjI0EnZ=KVJI`Dieh9m38P?j+}y^hXbjUKr(;UL=yJ3YH@ zqzoK(dUo9iM1-9lyFMc@y>u>|<5yhLvEZxWg*kr4_;Feket~Z%4G>}i%_swD^a9^b z8bH`z;M++92>T0sJ87gv)ff79(g48;=s1bSFZAu4QQ)yIZ6^&NtS&cWyV&>4 zmJ z#Qo;`m3iZSJl3WAn=J<*tmgadI2fVO!2;jz*krU0fR2^uV1aLUYSM` zSBnl}@s+Fyv#{g(9g7MJ6Am)|3lk2~^@Tp?6%sF~0f&V?vy+j9t}pUEvm(vvt^=Jc z;s}cpPSV;UKiAiClCCfE*%g4(PvH!_-uKMjEQoFa9V>C*>wUWg#8X&Z@Aop}1JreQ z-y<5Mdqve7JA!YIJmtoOfjIDuzD+)|a%u#uaSSALxY37!=_J+&9B_bxOyW2C!}quB z;k3Bpwr`JYT%53%ykc>}Uc7s8!d|?4al$?Y`^5?S6zmrZ`(>Rmf+!b0;a5B!sC|yh z$DduIe!P7CcOQf`PxzVI=nEOONDSba_@Y34Ir14N0YoHt#wikoI|AL=08w}Ke#|u6&>W{wW!PvjRJe>iEO=vHWGdzuw<>v|h3BRFb3h{(hsP=S?p#miLR9 zNWG{|dp~JH%;o*02{D)V{TinUF_-s!cKJ*f#9ZF@hm3TPF1+s_cxZHtbU~K=ANt;> z@c~up=q?}n>Dp*CO9kjMj$7iZs?-tnTl^ra7hRf+Vz>BJouVUcIU4^s-chB-)_?5V z<(rg~wa3RkYgtzg{7Kx@NsTRh;@f4il#>|!iO(`wTsD%y*~+k4VP(@B=!Q;asja?E z2PsR_Tm7EKFM#xWt3S{Uo!If#Waz|>x606MtTaXjudn>#L7mkEHS(*Z4N0KCN~}y0 z=&xLWiF5+}mEW&_v=$v9E==bXU$0g_^9pmwKdso3LeB|GCMGHLoSt_OeoCG_So6 zb&!TG2o5;JHbfqNVNg=MufD5&gYWYPPN_-CZ3$a$&-u6C4&M9AtN8 zVUROZVdQm!!@_{GdA*d3WM}2Z;t4%etvd9^ghyw1+?eo??UoyZQqb-Uj~fHFU1dER zd2F@Z9N*Maoj3C4ghMqPZcaGJ_RGzQ6xDFJS)_Q_sDizh+v8vMQjZ>fd%~gy7PluX zYG84DU>CHJR|AXN1D0>k8W!xqEDgMdx(DONUh0r|QJtE1I0R?MU0}8}VI~_jOM{$? z7+qktG}wD+^tfS`%LR7_Y)UT|X8HKy-s+|wLvYM;FuOZpmV?>diF$G{yIa&_Ra~13 ziZClq|Cx$ZJiV_94+A@1wM3(0V0XA9uNGd#!0vDZ;Z+n~|E*Qsm7|)#`$1hx{MgUc z{_#hB)#yVZI9^@h^o=))uN)ZNtF!Xts*K92PE zG0`xQl}dm1NL-G47#nw2t2n}W_}ZwvGvP?zPYDXS6t?ph+9 zgl`HG=$8HB?tN@>9piP-vl-0Vo0UVfxZbiy4wQ_lx}?& z#0`VhfT7aNrZFTyk zDeEjyk@V7(ovMNGxHMH`f;Eu-U79-Bq$5Cv=hD=n$LnlOpng2^IOF4$GSpY3oR5zJ z(l&W|%G~Ox` z(4thPYxKD2vPyEpCB?Z7YLzN1abiJ5tR*SCHV0B^Ny_fR0ugITiq)MM77$%7N%bD> zAf~<~HF6ZHr2$DxZ%%p3QoebtPor*5u|?jGtdqwg!L6yFx-S0vaMgEr{)}{nsvpsh zTT`5FUhCV!2(q+TH9{>^CoW9|nNmr~QJ1E0B00v8s^Gt-?4gdv)P!ITbu>YjAX|Oe zD1zt3;#d2qSJcR2q6i5pMQ2o1dVO9@)tK#QAc`o8BCeCrS0#7aRrR+^8AUsy3*q<`Wl(?}f)z_>lc#1Mtr3Q_#%H+IZb;|okNtxpRt5fMt z`sAX@oHsm$t=7eR9Ha)+^QSq5(T|YssT67aV67s3=(!ysc z8~1^<@L7tu{|ns%EMZ$Je(uNWzou?W8jyv`wxj_G0^1TDNf6kU>S01|l^4>$wp85@ zZI414*p?cwmoa>v>e9@ddgrA|>}Pu_zTz;o@U-noi?XcQp0p^-n(e6?XM?h=*`8u) zWRxb$n(e82Gj+mIvmCll^k32?xq0_($~!N<@No5u!ndikIn;tKj{RLKFjpZorWFY0 zXjT)jpzl(pmJ>&cG8e-lMk{V*0-Xluc=!iz)is?e{yN99kN z(%hDh*N;-g!o^{_hwT!VXgI75gFZG;nL9QR%+Y5Rmn|e#UlOvZ zAh;eupvK&g9=RIeOT%Cf+eU$V6bKHbU#V45!lfY_$F2%pxvX3)@kFfCwf*TtM)R-6c>{Tc=f|1QHuOglUA*qt0%6zJnYM}qi%lj^_03qqS9K~N= z-gk^~L3vNps-P*(?0k<~<`ls}UEeW*E6V#W!wezmyBx(|QQmhFn=8YhcS)U+g+VZv z2xSoEO#aHy?0XlmGAdjhdgc@bgzkXO%H$~Q>d@|1^Au)RhjzCb$k1FJvLw{gr<{{q z8+waEJALX~SJ#GIrqsPL$0KnV^f$5zK9bg;m@|?pq0n9&cCtzo0xia2H*1tapv^dB zv$bBP1_%^b7@u^c+M}?roRi+N4eb>yT}}#yU9JB~MK~=CNeGR%v8KN+^h^?5#b%9$ zP7iX!?YhwJSo0KK*M;_yF%VAIg$NGJ7=u)z=V7NhW+~msg;?SmKJcZlh z(57TSxGfGz$wo^Qz}mxGLhn9YcfWY?FV#Nr{IOh7yG8W6Ru0%HA)b4CymYL3b@c6t z4j|Lc?TI!a(9-Q;w}Ey9AkfzBA!`}Ay&{|_aA*AFPt>f@cb0RK&Hp>gIZ3#?vz(J? z^G@M(rsag0EsN(ItYMZ)D%|-jK~XGsNtA+#lK-sa0MTg93DeQU$mBlOdMm^ZwA@ zZKW`r?hiW;Y0!ys6{l~(iqIs=0648kILTe`6`@U(c?zc$p-q&5a9R=CL|L|69tw4$ zJfcbx<%dF>D1)d6G>I}0g+3ILDEA@3uEJ{{j*mHB?Kb4$(5}a-^m?ouQbWUoZH-6b zYmZlljC~}uTVPdsQC1GAp`j$>opRyhVZ}deGA_M%JR}*{I}4q}|jGEi_+fvc9zxo24@W*xRyhDt>M$M z6Wv*+*-gc#PEtQnzuc5aChoZ@kxazj6xx+3b&zaRc(6H`03z9@@Q~wlfETDAA9}2@ zk3L$MJqi+q?gA#VGjvknT;#D~s0fKtg>M`y{SKi1Z9!l550EaZ~^$IdP&1dETI zhXG;nv9k-=PTXqjBEIPtD)p1C&MrD@y8s%y0HTtu&MvCCnHW~gPn)Hv>>++0W_m_n z$*5L~VSF9NpZr37{fn=iSWs!}Yo|OQmA-bv3Ph~0-LL{t-q&tefeh={GOXIasy$Ww z&CgVgijO;0g(JUD+7Orc-f53wwDG;u9*{P^7wvJgUF4)kbK)ycRd<~-Cv77gM8uqv zwgwD@#hkRwsDZGUlV*Yy>jNU@oOFM)$O9tgob-?p(NUT|WiN`a|E2oLp%*3mWq>bA zSDKTdYCXUgr3aeb4WQIXV?*Np)iS_yBP(0G3({-}YQ5LU$X=6n zQ+Is&>1ZEpCJCM**fnW8a|5Y-P1?@fKm@xc&CLCVtkY{mv5Sj0pRU%cQx+#Y#Q7IH z^;1YnrLFS=;juVv&k2C2e{tHL697^F;xy+3qP!Xz-djX@M<2%DX!4e%6QUBIh5S9zj$C8a)DO@Q+T9U2@@{(iMNVdX!!5KczF> zqF1HwT||%f7Bdsn>*`ncI;o)2)V;3nKq}qq`VK^@dtKjw^!;AfcOZSgSNgtHY`cr> z)~rZ-E8`zFsZU3(NZW-BbZPs6v|Y$(OfwKn)~pHiAFF()h#aKIW_zh!P%7+p}6AN_Zq4nsXf>N_ZsQWshoOuU(|&)g^m9986mf zTw7uWtDV8}l(tqog9XyoYB5+br!In?Hs-|N@Oe7nBR>7KGbf(H=V@n7K&k1>Nsc?7 z)8@2a7cr;joH>E01~ldbMEK{#oG$a3iF3JdZMx!L#f{DCQdPS)&Hb|HWU9)^!eU+8 zd$U+LgW0OEE*+Wcxjc}eUY`!k`%M}nHUzVx&;+DepSJ4&O+beAY5OXMCLsL!G?y-9 znIZ%VY)A*Y>m*rYctWr|3sM568>AodDwr;!>u^d{BEWP*nm{a>XHLX?EA5$U9v~P3 z%@_gE?OW-}S{-qL@OmrF8y*sXfpB^&&8C~aN1D^YaAW-3G<9QPW5Pou+L*Q*cR6iS z8`JjW4G52oX zDoANqy_aa4!kg2a-5LeTemKyvk}a~$iBPi8-<)AkxuPH%_< z9jAR|Gwl6DD%k;eKb~0SpR-Y=SIxB&#=b~< z+tX&%42H`W>9o1C4iwwjmbM!t8dCs**)`Av#&cWR?ivVz0$-->eRGWs!5FX*3bHTr zWxBdX+q_V~UzJx89uSf$rbJl{diQlYFz+D=2N_)m<`ouAfali|JY{#FmTrVQ(%uD` zfMMYxHU!26iqR$zUGGTS>r6n{?MT}<+JH2-Bh8|)8m9nqH*QCI$OReS^Z){fu-~NZ z=7JQcMQ`7h^dCg>8JPMEPMAogV$?`l05qEDHjAh@xR z8S1i(jYvF&-DMdERBWIV{w&e+E&WQnQ})aILvfHc5|=Ic-NIwFM7K+la^PDU}-jW z<4iEf)E7(v2n6UbGz6ze2-H}Z(TX&UfEQ&-zGgOcAvnh| zo4SiK+Hu4Ukox*e!MnAjdYQ1VPgE}x_VpQi&645>aDAr#L00t=Z?DfBa;Q~3$vNCc z-da+C5r+QN7)7P2b=4w_*6 zhJG*2c=wgYPB=nvZX-$3(v00Dtkn^5X~u3L0U5ic87`<-oA}2G65JZ@D-E80(e5wF z;BmbX0soo|9s~qjmW-V*V|Q03xTiFBz8<^f;w8pyAW-MtWbAkouUN=<50(Z`CevcZ z9){HNLIaKdtt5qD3P3P>u(|+R`CEo1q8U5=#?6XMX)Z7?)j)7_0R(ES$mqF1+@^r< zk%4ohVO0;N5eViCP#Q5M^lNG2H;DaE##>cVy(9<_oa$x8_)x|khfo@B4`q6rI~qV# z|4@e8>?UFb1yuh~X85X->I3ncm8DK|$S$gXI8i+WSU!@do?9fj@X<{0cuDnvR{ay1 z;289R$mA^HlNs;XlA_yaGI9; z1kYvc61Z01CwMN?-6TCgH2qwLq{nEQBSx6*`ASLADN*#_ng7fw02Q>R*X%+-!heXS zjRjMJK0KeOJ|(JuArrh*QazUhQ02>+;P_GbF(iNKDwgkOIM(Fa&D6kk?F1m(lNUiq#|bhK%=7X)NSQ1_U=2awTI!rqWH!(x(lX-OOGM zl^Kf-nf(v2W5H=G%ntkr9TapIIDus_-YoSIELQ(kqIw9hd^-~iwt9ttfd5QJ3j(dY zlQ;?lWZbw5fi(HuU6>Y-dsD_910raqmSydGyKrUMyICYN`9UZ{{(dI-pfu!cMI-Bn znP6;5G#TXA4h$X;cXq0|M?Y?dViV;b~>IyfyJkptTapb z5`x&p)=W4g>Jnugg+h=9mXpxR)(q+Caiw|``aBbMt2>nU7A7^$oZ6nBKBH;qn9*ZT z8hd=a{&(u2fjq7$<001axeWcuB_2?|%)~$Vz53a}FEe5HvclrCUuN*x5v9V6!}d&E z{Jq*|(DqDNT~=5QNVjKrU-ubRD$O8$pNYE^)U$=}GhtO(X*nGIUJ@3a?dg~I&&v`n zw9Nof$a&dL=42EV>3wDhb`})^49?5uBpVPL=GC3qS?{uJ#^x~c`3?xqhSOpUv$K`^ zxyLAOc6R^c9Hd)wvSHd9G3%yqPBwE{Hf`kb(qh9GWHaW_ht{+WUzp9*Thn20j~qRl zxg=|YBt^t@=4LZTYtt!6C9$1Lvzg=drMFsk)#qnDb2qJ4Iy^sH+1UuByIT(Ftc8A1 zOYB^b_5Pd<^!l+@wm%kRJDK|sAQ}Oh?GGST7i7DUFYL}%K6Qho@r3i$fc=*yRU`og zx+-ELOS9d2ML)1L{*v`->xbqiwa$o_GEIj zy}=q2c$~v<*KIL^$DNVOV;Rd`2{f$y0pl_39aDyoiT%aCO$c90^qY1@B?L9s{O#t3^+Pr&yTvAdq6-~pC9Rz6c%E?vm@`7$i#jyrDt=eKe{xHp@5~4>xxHRrRMol zu8XYoYC3LsU1ZhcUzTh4#G=OFu3mO zs{GhV`F6SRb7Jev855dDwHB)vs+zFCW8<njOeM*OkT8{f zz_sN}CDC6Sb(KYx84OAF*G9ufM1zQs-H6ApN8W}gRo5#&=Ir*SmbT{BmNvp=-1jEc zZP@EkCv!itn~u%p5DjX`Eo(1e2H6-@%!wOsQXf}uj558Vv$53fVnpx7r!7|Joc^9O zREQYrdy!3$fk^mX)ZLt?0g>;$NN1675JTM@d9y2xp@J#BIf}YQ3*_1 zyfv}YkDTJAs@UmAQCD+sOA~1AqlkN3a+O2~u-+QQPu#4|K4NP*D>1gM<$_C;*c#dQ zpmj}HZH?ISUhk9uVOtcRe~a31DwL! z=f$_)s+zlQkFs5&BS?xUYI41AqPYKU>d1lLL}8?pBKw5id=ru699k+&OW#HDg4@){ zf!{@8wydzs(%(g_!44`FhO#q?KfjHWqn%M$Syou|v@_x&yf}eKjLn~4X^$T?HU#4Y znjn#|(q>?qfGFozattX>pb2#P{7OzAUT2zT*%@A1S#f!#s(Z%Ek1pQ%M|FZKTw0lu zkDvxAy+wIhrKdl4AP8naoj?dgyvr)hS2}<^oR^dpBLKRx((idmSY)g&qn0NMB%iV z?TzhCw)oz4l1a^`zfJSJ=0#Lc_7P0QxHx&W(-I zZS9RS+M6cY0UGL5S8A!@L{orzu54*g|Icyy-v(9mQ@PLoVgY4?nmaM7Y;T=j-8`Y~ z^r_8fHuX&DO7T1I`n?Y=@6AcA($K@pn=sZe zui`ge^LHCr&S8`(HOdx(O|`A)NOhcHW}Mn`qvKC|GJbtuWi-b2N_Fm@`$<%DR?}2k zX*#{6eJ?)bHGj{^)%Jm_UDu(av{htopQzgzO-<7qrGuw8x3o9SIJ0r;>C?n|)u2w} zYD*8t+GoeM(xxLxiYUh2lUdHd*D_dyRxLqpLHAL0_(c@jMSK2PO z-aVoy(Q&-s_*BnA{h%ls<%F2UH+Q;^I_!kQ4j+5W*pvS2^plS}@q{s>#vUo8))&)pxt+nPGTPEhM zp_&%k;4pdI38RKe!23adeBAFezk4A+rLisF(waZ&q?1k9cvI$0EL~eRdE10cm;0XOz$0=OFit4=0~}@K0oh z=NT7Y&+!VreOATspMOp$pYIW-d?d|3r;n@1MOXivQNNH$Tb_}7oE!W;lzc_QyPkch z-jdkefy6D*^Objz`P8Ohrup+#sJA=>GRvQ@>h$K0KuJtg;YX*CstA8>&W5v9aG?sL zTHQjYK)2wCrVZ|BUZT89OKr$4%}W#=Fha@)*e+4@z(U%%M2-5jgLGl8Vw=!(p)(D1 zl|E?NK_vGigqN#|rST1)`UiHuoRdh>Hoog7srePkTd4fHLGglZem>4_^=k`PDAXpY z8U-XbzmlUB zL#bKl+b8h2O4$QrsYCxels)3p7#4*mXrR>#N=845bc=zDC(?dyU}%A>kp5wQE#luHfquu((D(r|QI@#J2mkXsrM5;0_(oL7z#ZOBG>Y_uT* zPrl4ouK#Gi9t)=Yb@EYYq~wc$=Dz*)$+(jw(*y)JXeNoiJ{fliG;w`0?mCgaAsKft zEFdH-q*XqNZO2`%=ELHKZZhuUwE5{{{~PIP-Qn>~5BUA#8^84TJVeBk6&4R%k4^4< zW71;?@VZfY{ADLech>Xv1F z&IhOy1~TNglrxa^`7Od=lx0AT+v0b2_#+F#P6qro703a%I1B_Bu*5npA;91^_0w^T z27{HsOYczLoo=u)vV6HiWz62K_Rv4cH#i9mvc7{mFm#Zze^TkJfhXue`jcYaM%1J< zPyeg}^V&Cvx4yU(*G51=yW+Mu5d#q1n`4+Yy6`x z{Gst~+x>JLeeHMN7n*TcT?Q@>I)Bv!T?>ER-!_j0t&ETU+COmrmF3Ng<*Y34uvpGY z>F^(nGI7(#mG@j+{Mx^vJ0DNzX_bky@gnN3${cjCaZ<=mrN&8DB`p{yT_r6XrA5GF!A(x=NSiVB}jREmG)f@j4W z#uWGrwDAJrCw};>^8!tfg3b$+c)=RwyQ#k0uXh9#tVS7^Stu{qlf3k3r=NT<)+J8Rq<;4@i+b{$FJSxhYns* z_DgGA!NLE5=5WZ|(RoE>&9@hUbn_L(UMov##y@;RRs2gSCgjDR`gQSL-}*hezrjr* z9`g}qaWB3U{Vp^1p79ks{oUekzGcQ{6Uofj6cE$c;3BuiG!MaqT}_}z8(iep1Vq^2 zBDWAI@TQC08p8rY!a|htri*Obj?&~d$gmUl(MH-v`S3Sz@|2qYeQyi2ni3Fu{Wx0 zq79j`HyUj)@M8Y&Derx2{$R?#XU%_vKQy;RvGF?!OAEx(K33jm@w}b>;axr!0~V> zh^=H3g*Aa@K5^NT5Ge4e8w-t50t7P_nxISAvCsrqeCozR2w2rtHx}Hnf&dRFMv=M% zJhr;A&;)pFHDf`)M3H=tdz)1xnDU>yIHGR`ec|*7LXSYBM{`Z+3#Z4x>ne);LKHa! zMY0jUT~&M&*Q;RfQ@1Po0Y`lUW{0xxID;@qpgGh6(!dV)5py8I>`;BpRd^u$cgRnb z$dt=PiSJd#d0u>n3K~xRUUB>@leoUtvD5vE0*D5HrU4)g>~udW0HlGPs-KBSdhPPjz(!e~Lf&JRv&UcgZ5n&yj*3%pwMGMM>d;{wm# zE7xCayu!0Lok0vY&15?4E>P23rpI$}j z5A$6g|0)&yp!s^&Df1=1>s_bJm-w!CozfrTyTNq|M5lnJQ$WV(2G=R`0lpigQ{t_B z>}Ro8aa*jyU}()^kwO3H2Os6(+Z^!^!{DzYZ*^ZEg$UzY-6w~EFuv8}cci3qKnDL- z8L@+5%y&ud@G9)@GVh7ZEX?ooDjtZx=Tg(r_j#HAdW3oXk{4Os2!oIdXhs+a!~5L`17Uc- zjIcI!{jTPUxFs7b8n(jo%#|c-VY1% zB_~C+!JWr6NqpRyD!WFsrs;IKS%~dxQ9La{s8Yqay`#|g&0It zph+u$@^m*ZYfk&X)O|!gkSmD_ulhZ~2bkk7mBA^wC&X#xm&dAQbXR-c)A8>rgA)p? zJzlt!(Sv1+@9&9tV0c4tyiLmY_e4CC z^!;7LldX?x?hA!4c;2h==BnVp!V4Y;+eT~>vRv?@XRm@%PP2w!k{?Y#>=)&G(qh+| zfYdL_7uDq^7X+DOUh;xhyp$`VXPK8g+HkGF<7F=#p$im*iKLxS%$d6;=pucFI38L# zFMHf@a6Fg{*LvZ>r2>*=KrjcE!a^)&t(V^~DS@PGy#o)5ex#Kk>89tck9&6xemLO` zk6#KhtVt2LqvzS1fz>`3vxQ(z=rn=0)_L|kT@z?)o!8aLZ?cSa@?G{R(w1<1JASBh z@SBluJM)JK7e38x!YvRUZ+rFwuRx@I+v6a4FOK-o>APOV`|*V8U~u7GrhRdCE*Qag zll4?VZ~*E%69Q4uCi$wmDa*t6JWqe1kcVP^K>gt)fs}nu48)WLZT38Urp-gqBv9|i zr7F7VqrJ`2xuJL$uUmfTReTcXYl0z#54o|f;}9=Pa#_#w%)ADouR!y$Fd!Vac=p>} zK>E7Hv!80 zOE9AFm4qzem=j_6#J9-2hXsYsXXHr$90UBw{>nS^(G(f8El&brQrnuua$FI03KCCv_SH2u>`p1nZ zZVme0Ks{_AGzByh50D1hRD5LJOjHgk#U zLf>ktySYVmp^tEqR&WDqE+6=gvt3Cm=K7fd(EvDdGlmyxeDCu3#IC^}eCgYUU%4@Z z)bo71ZqyhhLNJkC6A*QtZ`X~QfUxs?yKWQ$1?Ky9!KN`RAeacQ3A#k3S+8|#vJ=mI z-+q^fyH@0>zV%!XsskF;0qH;A_BMCgfG}I&^Shwp9zdj7;N!@L(0y*zbodq5@on#+ zai^|9pZKh9L0yiodJoik;35M*S>k&O<6F9+hijZ3j4gw;cLw~UXS9`x-WzU*xx7zjO-KJ*Pl52X)% z17XI8zKtG$NV7=vaCZhp^vH#O@hkp`B96?DGUr)Cf0%FM6tihYL;gfL-)b#z0@gYs zKdp5}Q@*{K^QJr}>@)Nc*wp4pJd+UJdQe(2Dld2@os!P73MY;syQUXHZN zPuuj7Sm_9i%DepIry7%^u(G4LUzd&wf9+1lW;E#&xVAihG;yxQd7bVGr)+X;$MIIQ zOUrEye3I%vPxA83?QO2qcvuwLn%a}Yy+ItFacJ1u(!$AMzO^OFPivYso)HuBj)@L@hG`CGb=;=)iAd0g((x;jfU<(()5KYjSS~5N2C)PTk__Jw5g#JKrozugfG0F@kc@+JZrw>lRUtJ_<%QY<40Z z*+_L$+I0^{$WLsZSm3-^hM=kOjQphL8Ex&@m8_?F5Lo`=vnH40kRFm;|JC>I^38oh zFpvN0+vAWP5;vEz2Gh|PM2rHOr8SVU%Y1tr0whK)lW(qT&cwf5c#rSB?O6L#{2n<| zmb=$Ie0>yiuOIx)=Zk;&F^vH8o6b;7yIz@mN2hV`_8D8TrOZ?K1w1%uI=1gUuWv z%w@KRSs6id=i4f>{Lv+7{(hf#FXU5}LLdPxO7p$2@wT%hgtyXh6Ct%K5@xbwp{ynp zOl8;?N_X!_I$LQW|{i6r=mGehL+1)b!EkM5DyGM7Y7I{t*QqfS41 z>~W({KXTmhC!cWov13j=@vtMuoOn9!I%xRW!-o$kW0fDtEsp}xg*$13MV-4a`1zP) zMje0bnE%0I#DB18ZsA_o)TufEpMFNutigv!AU9nyfkZl{d!Z+jiLHbX?ej8u<_nV= zo2Qyiy6A&iqx{(8esabs%`cugd9nkuY)N zrmOsLKz+ab_@>E3?1@d1Sj>(*)Nl(Z7f!x)#Oc znn1(MO)*oSX1DY3PKht&#@lPT4upPLz^}paJ8f5gEixe0CyM#;wAkXkt)(+pLxe z^@GW7CpP^+GqCY+6240&W&K}ztuq4=Ri;s<-(6gSoUv&txxhHNf7*zLq!X(AS!jH7G>Flf7w80|IkyC1p~<1fLR;a(%Z^z^2@NoPy|(o25WyY5+K zllP$$BrhNZYMn8o$v8aGWJtaVy73{cj{kiO$)#GUsqa}bKbowfvAw;(uRqzW{VW+M zscqH(QyZtVNI2^FlaCpVx8-NHG?R}=%HlGXL-NB3VPwqZ0@)EloAC}1JD5->j_B@7 z+iQ3-LK9}rXk(J%sh(w2LPst7Zv{c=b9=WZjLBD`(-7dsQ zm9s&1OZrCzFX+i8r(bbHpz3N_6wBf`&obF)6H}3FxF=lR^*N@MoVBN9!<&3>vrSpS zJl^E8;hvIAzUQ)G5VH-?WWzwpzUQ*xo*uW81lx4Dr`YzteDC_eB-&t#|4XuA+2#gH z+aLJ+_>bA<))b0-AbT^ij|@TD|B#77Pox?n0R(eMtO?Zk(65%w^a9`7kt#^>p#&ga z9MA+xZ1Kao`u#~EWuJgMz)bVgrZr7$##nXEoo{7$h7cQA^ho@iRf@c34i~}(GJ;PegBT&MO~O*pCf}C-&CE7DW=5-CyK9dvO=AQv(LvIRe3Swv=IwqF zS*}xj;`6hnk~(Pu&3+>3gItCZ0L~xi?3} z(s1c}bD#R%%?qxYGfjQ!^MWfs!J^v|6aK>IccxNxGYQY*Wj2;=Bojl-;`|VEznPIM zBo~|A$~~|1dmZ{rN=jBfku4t+3P=^tn$ir*T~{2^3l@Xu3755M(9ZLPU)2@o;WHvG zgWTqa!}J6rlmfQTm_RdGnk_}Qx7iHQRYb?z{62e?Y8t26<_~QsV^5(k{czv1LXrbQ zD(5av@ugqgS4tHudx=wD`nxrh*F>{l`XlyX!`Ud7lerx}zo(VrM+;A4ax+UAvl>P% zI;pa$QJE5i^A5kNHku>3h4fFKj0%@2jSjz3%&gDdi#sbAXeAytxOL2NzAA0z?c+H zFM8T$PM_X7gPlLUNkw0bVUeiH`cI0;UXyIY;RelD29aI;3l^4@$ zt=qGlgz{$xxcBYOy*b3aI0)uqg;y)Pi7eJ4d7;gRwJdr$va62{LQyU^ua`u#e((_D z54#{U%(~mAu2UO{g~>wY2W86zttgjvx1B+XBUZ_PmSR_#<;!0D#X(i?NWPvS=B3Y> zFA2il^@p0gw2kDF)?9CG@v&hkrpM{ zE6Ct!0o&P#XvmLkq0BVBn?XC~?H0GLWN9W#p9$?c9gw~Hi8I+?I|pJ`kZAO(pqt*v&;||(OS>xIjQm~euks$s!XUT~e|32aY7B@@gt;P}$zpYk{G1eq@hic(jxyG|Ki6%L{FmlUTHrue|m4tt1X6UhBgpGkAI%N`jo7>-8sg76#c` zHyNAPt``Mif9I`2L1B>0P768=$Uo(}!lHm&X@h*bq*pGyC8)TK#lRXbe~h@hytq|L zJ$dcRY@-wS%`Rl4PTJhAI%iH}=pqI$XEb?vsmn|Sk=}znL_1A+_F9nblA?%C=1q<6VV=Vl-^p$joskBKF_$=B=zVRo#-+_@6# z&*Wf9R`)buHmli8ZynE^=+>1Y%<(6ZcH!rGpT!1_MzNo>WeUSV%$onOQAg`hM8+8m zy-d9_RI-xl#R%LIWUBNbcQ3DkpDMXkeg{s@ae>%4(A=8vG}kLB*c}^C9&*O5QGP4`hK>Co7;k;L6sI-W+k6fXq|&KvNQVap!_D%{Ft+Oid)9 zs*wN)-#eTHKqR=sNzgkN-WgQ<#Y)hdl6MC79zbuAU}@l)pZx$a{{l@TKoUTHxls=O z`D7`Wx=VxI&1dC+w6ZkdvvShUKDlsNP_f*$(ub1E0&XD69f3a5%3XoIBmzQqpt<@0 zr0iXRy(9vJ>s^7pB+^IbMt=TrP(f=RNL{e2D@o(s0aq+!TzE>|y90YCu8*wH?g_jj z?L%2)0rh)wloihR1P34Po>KLmV9XJ^GktU6eL=ZkUy1dyu5fYraKx3F6-d?2WJ*ow3p zMIQ+4Z=mlc67gG<<`NDFiGW5TAY~tP5&>cRpp$4fk?5hoJ6dZ2gaH7J0RR#3p`dc# zs8a#`f_3Trj&P-6^-wTYzh=o()V+u5)3LHw|(nJ z$wvcwr>CFvji0_OH0U;gNC-9(0%?U`yEM0WfYf~~=x=_`2S_WA1$=W-RG81nZ(%-Z zTgg*$l~|5gXkJ=b?fd{lBS6y#Fw6}H^8>hIW?<^B4(g2`0BL2l_`z|s(mxkI6I84T z;_ABKsIL7f`HXnmk7=d9wDMdKpHUYaQUK7%bFL8}qxM{2zZMOo=5s+8^UHle+IUWW zvr@$EFUtITU~ZfVqAJjA-2nAdzGx}Z0;&3UN$O5Vy!u@DVj!<359l5I*Z%dCd@VSFt5?7m}!^sALBLCVTUfvt|HKYe?xvZ-vH%(wP)&_j=OJ+Mw zfWz9L&iuNKCLqjO`SnogN4+rQheyrLA`tvaze5Uy8^1$pf-VqVuLbrqyb%~yuLb%3 z#V=pUUBX?|F=Dg+m7+CP8F}e!=L2;KZJ5JLI3~& delta 31025 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 SE8C}M28ES>9+T-;|Nj6)Co|Ll diff --git a/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.rs b/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.rs index 8205bd5643..84d1d01754 100644 --- a/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.rs +++ b/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.rs @@ -762,6 +762,345 @@ impl ::prost::Name for SubscribeWelcomeMessagesRequest { "/xmtp.mls.api.v1.SubscribeWelcomeMessagesRequest".into() } } +/// Client -> server. Sent one or more times over the life of the stream. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SubscribeRequest { + #[prost(oneof = "subscribe_request::Version", tags = "1")] + pub version: ::core::option::Option, +} +/// Nested message and enum types in `SubscribeRequest`. +pub mod subscribe_request { + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct V1 { + /// Each frame is exactly one of: a mutation, a Ping, or a Pong. + #[prost(oneof = "v1::Request", tags = "1, 2, 3")] + pub request: ::core::option::Option, + } + /// Nested message and enum types in `V1`. + pub mod v1 { + /// Add and/or remove subscriptions in place (applied atomically per frame). + /// Topics use the kind-prefixed binary representation shared with the + /// decentralized backend (XIP-49 §3.3.2): the first byte is the topic kind, + /// the remainder is the identifier. This RPC initially serves + /// TOPIC_KIND_GROUP_MESSAGES_V1 (0x00, identifier = group_id) and + /// TOPIC_KIND_WELCOME_MESSAGES_V1 (0x01, identifier = installation_key); + /// a topic whose kind the node does not serve fails the stream with + /// INVALID_ARGUMENT. Future kinds (key packages, identity updates) are + /// adopted via the capabilities advertised on Started. + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct Mutate { + /// begin delivering these topics + #[prost(message, repeated, tag = "1")] + pub adds: ::prost::alloc::vec::Vec, + /// topics to stop delivering + #[prost(bytes = "vec", repeated, tag = "2")] + pub removes: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, + /// Catch this Mutate's adds up to the live edge — history, TopicsLive + /// markers, and the wave's CatchupComplete — but do NOT register them + /// for live delivery. The markers then mean "you have everything as of + /// now". Combined with half-closing the request stream, this is the + /// bounded catch-up ("sync") mode: the server finishes the wave and then + /// closes the stream itself. Removals in the Mutate are unaffected. + #[prost(bool, tag = "3")] + pub history_only: bool, + /// Client-chosen correlation id, echoed on this wave's CatchupComplete + /// so completions are attributable when waves overlap. SHOULD be unique + /// per stream; 0 = no correlation requested (still echoed as 0). + #[prost(uint64, tag = "4")] + pub mutate_id: u64, + } + /// Nested message and enum types in `Mutate`. + pub mod mutate { + /// A topic to subscribe, with the cursor to resume from. + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] + pub struct Subscription { + #[prost(bytes = "vec", tag = "1")] + pub topic: ::prost::alloc::vec::Vec, + /// Deliver ids greater than this; 0 = from the beginning. For a newly + /// joined group, a client SHOULD seed this from the welcome's encrypted + /// WelcomeMetadata.message_cursor so a new membership does not refetch + /// pre-join history it cannot decrypt; for a new installation's welcome + /// topic, 0 is how pending welcomes are collected. + #[prost(uint64, tag = "2")] + pub id_cursor: u64, + } + impl ::prost::Name for Subscription { + const NAME: &'static str = "Subscription"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeRequest.V1.Mutate.Subscription".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeRequest.V1.Mutate.Subscription".into() + } + } + } + impl ::prost::Name for Mutate { + const NAME: &'static str = "Mutate"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeRequest.V1.Mutate".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeRequest.V1.Mutate".into() + } + } + /// Each frame is exactly one of: a mutation, a Ping, or a Pong. + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Request { + #[prost(message, tag = "1")] + Mutate(Mutate), + /// liveness challenge (e.g. probe the link after resuming) + #[prost(message, tag = "2")] + Ping(super::super::Ping), + /// answer to a server Ping + #[prost(message, tag = "3")] + Pong(super::super::Pong), + } + } + impl ::prost::Name for V1 { + const NAME: &'static str = "V1"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeRequest.V1".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeRequest.V1".into() + } + } + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Version { + #[prost(message, tag = "1")] + V1(V1), + } +} +impl ::prost::Name for SubscribeRequest { + const NAME: &'static str = "SubscribeRequest"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeRequest".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeRequest".into() + } +} +/// Server -> client. +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SubscribeResponse { + #[prost(oneof = "subscribe_response::Version", tags = "1")] + pub version: ::core::option::Option, +} +/// Nested message and enum types in `SubscribeResponse`. +pub mod subscribe_response { + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct V1 { + #[prost(oneof = "v1::Response", tags = "1, 2, 3, 4, 5, 6")] + pub response: ::core::option::Option, + } + /// Nested message and enum types in `V1`. + pub mod v1 { + /// A batch of new messages; group and welcome messages share the stream, + /// depending on which subscriptions are active. + #[derive(Clone, PartialEq, ::prost::Message)] + pub struct Messages { + #[prost(message, repeated, tag = "1")] + pub group_messages: ::prost::alloc::vec::Vec, + #[prost(message, repeated, tag = "2")] + pub welcome_messages: ::prost::alloc::vec::Vec, + } + impl ::prost::Name for Messages { + const NAME: &'static str = "Messages"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeResponse.V1.Messages".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeResponse.V1.Messages".into() + } + } + /// The first frame on every stream. + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] + pub struct Started { + /// The server's ping cadence (ms): the basis for the client's staleness + /// threshold and the server's reap deadline. + #[prost(uint32, tag = "1")] + pub keepalive_interval_ms: u32, + /// Optional protocol features the node supports on this stream. The node + /// silently ignores request types it does not understand, so a client + /// MUST NOT send an optional request type whose capability the node did + /// not advertise (it would hang waiting on a response that never comes). + #[prost(enumeration = "Capability", repeated, tag = "2")] + pub capabilities: ::prost::alloc::vec::Vec, + } + impl ::prost::Name for Started { + const NAME: &'static str = "Started"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeResponse.V1.Started".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeResponse.V1.Started".into() + } + } + /// Sent once per Mutate that adds subscriptions (a catch-up "wave"), after + /// the wave's last TopicsLive: everything the Mutate asked for is delivered. + #[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] + pub struct CatchupComplete { + /// echoes the Mutate that started this wave (0 if none given) + #[prost(uint64, tag = "1")] + pub mutate_id: u64, + } + impl ::prost::Name for CatchupComplete { + const NAME: &'static str = "CatchupComplete"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeResponse.V1.CatchupComplete".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeResponse.V1.CatchupComplete".into() + } + } + /// Emitted when topics finish catch-up, AFTER the last history frame for + /// them — including any live messages that queued up behind the catch-up, + /// which were equally historical from the client's perspective — so every + /// later frame for a listed topic is live tail. Informational only: delivery + /// correctness (no duplicates, no gaps) never depends on it. Re-adding a + /// topic re-runs catch-up and re-emits it; receivers treat it idempotently. + #[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)] + pub struct TopicsLive { + /// kind-prefixed topics now tailing live + #[prost(bytes = "vec", repeated, tag = "1")] + pub topics: ::prost::alloc::vec::Vec<::prost::alloc::vec::Vec>, + } + impl ::prost::Name for TopicsLive { + const NAME: &'static str = "TopicsLive"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeResponse.V1.TopicsLive".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeResponse.V1.TopicsLive".into() + } + } + /// Optional per-stream protocol features (none defined yet; future + /// revisions add values, e.g. fetch-over-stream lookups answered with the + /// same read view that feeds the stream, or new streamable topic kinds). + #[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, + Ord, + ::prost::Enumeration + )] + #[repr(i32)] + pub enum Capability { + Unspecified = 0, + } + impl Capability { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + Self::Unspecified => "CAPABILITY_UNSPECIFIED", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "CAPABILITY_UNSPECIFIED" => Some(Self::Unspecified), + _ => None, + } + } + } + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Response { + #[prost(message, tag = "1")] + Messages(Messages), + /// sent once, immediately on open, before any catch-up + #[prost(message, tag = "2")] + Started(Started), + /// idle liveness challenge; receiver MUST answer with Pong + #[prost(message, tag = "3")] + Ping(super::super::Ping), + /// answer to a client Ping + #[prost(message, tag = "4")] + Pong(super::super::Pong), + /// these topics just crossed from catch-up to live + #[prost(message, tag = "5")] + TopicsLive(TopicsLive), + /// a Mutate's adds are fully delivered + #[prost(message, tag = "6")] + CatchupComplete(CatchupComplete), + } + } + impl ::prost::Name for V1 { + const NAME: &'static str = "V1"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeResponse.V1".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeResponse.V1".into() + } + } + #[derive(Clone, PartialEq, ::prost::Oneof)] + pub enum Version { + #[prost(message, tag = "1")] + V1(V1), + } +} +impl ::prost::Name for SubscribeResponse { + const NAME: &'static str = "SubscribeResponse"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.SubscribeResponse".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.SubscribeResponse".into() + } +} +/// Liveness challenge/response, shared across versions. Either peer MAY send a +/// Ping; the receiver MUST reply with a Pong echoing the nonce. The sender closes +/// the stream if no Pong arrives within its deadline — how a node reaps a vanished +/// peer (e.g. a mobile client the OS suspended behind a proxy that still ACKs the +/// transport). +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Ping { + #[prost(uint64, tag = "1")] + pub nonce: u64, +} +impl ::prost::Name for Ping { + const NAME: &'static str = "Ping"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.Ping".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.Ping".into() + } +} +#[derive(Clone, Copy, PartialEq, Eq, Hash, ::prost::Message)] +pub struct Pong { + /// echoes the nonce of the Ping it answers + #[prost(uint64, tag = "1")] + pub nonce: u64, +} +impl ::prost::Name for Pong { + const NAME: &'static str = "Pong"; + const PACKAGE: &'static str = "xmtp.mls.api.v1"; + fn full_name() -> ::prost::alloc::string::String { + "xmtp.mls.api.v1.Pong".into() + } + fn type_url() -> ::prost::alloc::string::String { + "/xmtp.mls.api.v1.Pong".into() + } +} #[derive(Clone, PartialEq, ::prost::Message)] pub struct BatchPublishCommitLogRequest { #[prost(message, repeated, tag = "1")] @@ -1057,6 +1396,20 @@ pub mod mls_api_server { tonic::Response, tonic::Status, >; + /// Server streaming response type for the Subscribe method. + type SubscribeStream: tonic::codegen::tokio_stream::Stream< + Item = std::result::Result, + > + + std::marker::Send + + 'static; + /// Bidirectional subscription (XIP-83). One long-lived stream the client mutates + /// in place via add/remove topic deltas, with WebSocket-style liveness ping/pong. + /// A single stream MAY carry both group-message and welcome topics. + /// gRPC-only: bidirectional streaming has no HTTP/grpc-gateway mapping. + async fn subscribe( + &self, + request: tonic::Request>, + ) -> std::result::Result, tonic::Status>; async fn batch_publish_commit_log( &self, request: tonic::Request, @@ -1656,6 +2009,54 @@ pub mod mls_api_server { }; Box::pin(fut) } + "/xmtp.mls.api.v1.MlsApi/Subscribe" => { + #[allow(non_camel_case_types)] + struct SubscribeSvc(pub Arc); + impl< + T: MlsApi, + > tonic::server::StreamingService + for SubscribeSvc { + type Response = super::SubscribeResponse; + type ResponseStream = T::SubscribeStream; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + tonic::Streaming, + >, + ) -> Self::Future { + let inner = Arc::clone(&self.0); + let fut = async move { + ::subscribe(&inner, request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let max_decoding_message_size = self.max_decoding_message_size; + let max_encoding_message_size = self.max_encoding_message_size; + let inner = self.inner.clone(); + let fut = async move { + let method = SubscribeSvc(inner); + let codec = tonic_prost::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ) + .apply_max_message_size_config( + max_decoding_message_size, + max_encoding_message_size, + ); + let res = grpc.streaming(method, req).await; + Ok(res) + }; + Box::pin(fut) + } "/xmtp.mls.api.v1.MlsApi/BatchPublishCommitLog" => { #[allow(non_camel_case_types)] struct BatchPublishCommitLogSvc(pub Arc); diff --git a/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.serde.rs b/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.serde.rs index 86ca7f1ab0..6526357791 100644 --- a/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.serde.rs +++ b/crates/xmtp_proto/src/gen/xmtp.mls.api.v1.serde.rs @@ -2352,6 +2352,204 @@ impl<'de> serde::Deserialize<'de> for PagingInfo { deserializer.deserialize_struct("xmtp.mls.api.v1.PagingInfo", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for Ping { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.nonce != 0 { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.Ping", len)?; + if self.nonce != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("nonce", ToString::to_string(&self.nonce).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for Ping { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "nonce", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Nonce, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "nonce" => Ok(GeneratedField::Nonce), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = Ping; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.Ping") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut nonce__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Nonce => { + if nonce__.is_some() { + return Err(serde::de::Error::duplicate_field("nonce")); + } + nonce__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(Ping { + nonce: nonce__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.Ping", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for Pong { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.nonce != 0 { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.Pong", len)?; + if self.nonce != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("nonce", ToString::to_string(&self.nonce).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for Pong { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "nonce", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Nonce, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "nonce" => Ok(GeneratedField::Nonce), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = Pong; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.Pong") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut nonce__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Nonce => { + if nonce__.is_some() { + return Err(serde::de::Error::duplicate_field("nonce")); + } + nonce__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(Pong { + nonce: nonce__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.Pong", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for PublishCommitLogRequest { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -4020,6 +4218,1274 @@ impl<'de> serde::Deserialize<'de> for subscribe_group_messages_request::Filter { deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeGroupMessagesRequest.Filter", FIELDS, GeneratedVisitor) } } +impl serde::Serialize for SubscribeRequest { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.version.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeRequest", len)?; + if let Some(v) = self.version.as_ref() { + match v { + subscribe_request::Version::V1(v) => { + struct_ser.serialize_field("v1", v)?; + } + } + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for SubscribeRequest { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "v1", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + V1, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "v1" => Ok(GeneratedField::V1), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = SubscribeRequest; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeRequest") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut version__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::V1 => { + if version__.is_some() { + return Err(serde::de::Error::duplicate_field("v1")); + } + version__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_request::Version::V1) +; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(SubscribeRequest { + version: version__, + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeRequest", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_request::V1 { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.request.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeRequest.V1", len)?; + if let Some(v) = self.request.as_ref() { + match v { + subscribe_request::v1::Request::Mutate(v) => { + struct_ser.serialize_field("mutate", v)?; + } + subscribe_request::v1::Request::Ping(v) => { + struct_ser.serialize_field("ping", v)?; + } + subscribe_request::v1::Request::Pong(v) => { + struct_ser.serialize_field("pong", v)?; + } + } + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_request::V1 { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "mutate", + "ping", + "pong", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Mutate, + Ping, + Pong, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "mutate" => Ok(GeneratedField::Mutate), + "ping" => Ok(GeneratedField::Ping), + "pong" => Ok(GeneratedField::Pong), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_request::V1; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeRequest.V1") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut request__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Mutate => { + if request__.is_some() { + return Err(serde::de::Error::duplicate_field("mutate")); + } + request__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_request::v1::Request::Mutate) +; + } + GeneratedField::Ping => { + if request__.is_some() { + return Err(serde::de::Error::duplicate_field("ping")); + } + request__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_request::v1::Request::Ping) +; + } + GeneratedField::Pong => { + if request__.is_some() { + return Err(serde::de::Error::duplicate_field("pong")); + } + request__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_request::v1::Request::Pong) +; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_request::V1 { + request: request__, + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeRequest.V1", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_request::v1::Mutate { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.adds.is_empty() { + len += 1; + } + if !self.removes.is_empty() { + len += 1; + } + if self.history_only { + len += 1; + } + if self.mutate_id != 0 { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeRequest.V1.Mutate", len)?; + if !self.adds.is_empty() { + struct_ser.serialize_field("adds", &self.adds)?; + } + if !self.removes.is_empty() { + struct_ser.serialize_field("removes", &self.removes.iter().map(pbjson::private::base64::encode).collect::>())?; + } + if self.history_only { + struct_ser.serialize_field("history_only", &self.history_only)?; + } + if self.mutate_id != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("mutate_id", ToString::to_string(&self.mutate_id).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_request::v1::Mutate { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "adds", + "removes", + "history_only", + "historyOnly", + "mutate_id", + "mutateId", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Adds, + Removes, + HistoryOnly, + MutateId, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "adds" => Ok(GeneratedField::Adds), + "removes" => Ok(GeneratedField::Removes), + "historyOnly" | "history_only" => Ok(GeneratedField::HistoryOnly), + "mutateId" | "mutate_id" => Ok(GeneratedField::MutateId), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_request::v1::Mutate; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeRequest.V1.Mutate") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut adds__ = None; + let mut removes__ = None; + let mut history_only__ = None; + let mut mutate_id__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Adds => { + if adds__.is_some() { + return Err(serde::de::Error::duplicate_field("adds")); + } + adds__ = Some(map_.next_value()?); + } + GeneratedField::Removes => { + if removes__.is_some() { + return Err(serde::de::Error::duplicate_field("removes")); + } + removes__ = + Some(map_.next_value::>>()? + .into_iter().map(|x| x.0).collect()) + ; + } + GeneratedField::HistoryOnly => { + if history_only__.is_some() { + return Err(serde::de::Error::duplicate_field("historyOnly")); + } + history_only__ = Some(map_.next_value()?); + } + GeneratedField::MutateId => { + if mutate_id__.is_some() { + return Err(serde::de::Error::duplicate_field("mutateId")); + } + mutate_id__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_request::v1::Mutate { + adds: adds__.unwrap_or_default(), + removes: removes__.unwrap_or_default(), + history_only: history_only__.unwrap_or_default(), + mutate_id: mutate_id__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeRequest.V1.Mutate", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_request::v1::mutate::Subscription { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.topic.is_empty() { + len += 1; + } + if self.id_cursor != 0 { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeRequest.V1.Mutate.Subscription", len)?; + if !self.topic.is_empty() { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("topic", pbjson::private::base64::encode(&self.topic).as_str())?; + } + if self.id_cursor != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("id_cursor", ToString::to_string(&self.id_cursor).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_request::v1::mutate::Subscription { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "topic", + "id_cursor", + "idCursor", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Topic, + IdCursor, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "topic" => Ok(GeneratedField::Topic), + "idCursor" | "id_cursor" => Ok(GeneratedField::IdCursor), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_request::v1::mutate::Subscription; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeRequest.V1.Mutate.Subscription") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut topic__ = None; + let mut id_cursor__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Topic => { + if topic__.is_some() { + return Err(serde::de::Error::duplicate_field("topic")); + } + topic__ = + Some(map_.next_value::<::pbjson::private::BytesDeserialize<_>>()?.0) + ; + } + GeneratedField::IdCursor => { + if id_cursor__.is_some() { + return Err(serde::de::Error::duplicate_field("idCursor")); + } + id_cursor__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_request::v1::mutate::Subscription { + topic: topic__.unwrap_or_default(), + id_cursor: id_cursor__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeRequest.V1.Mutate.Subscription", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for SubscribeResponse { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.version.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeResponse", len)?; + if let Some(v) = self.version.as_ref() { + match v { + subscribe_response::Version::V1(v) => { + struct_ser.serialize_field("v1", v)?; + } + } + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for SubscribeResponse { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "v1", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + V1, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "v1" => Ok(GeneratedField::V1), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = SubscribeResponse; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeResponse") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut version__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::V1 => { + if version__.is_some() { + return Err(serde::de::Error::duplicate_field("v1")); + } + version__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_response::Version::V1) +; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(SubscribeResponse { + version: version__, + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeResponse", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_response::V1 { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.response.is_some() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1", len)?; + if let Some(v) = self.response.as_ref() { + match v { + subscribe_response::v1::Response::Messages(v) => { + struct_ser.serialize_field("messages", v)?; + } + subscribe_response::v1::Response::Started(v) => { + struct_ser.serialize_field("started", v)?; + } + subscribe_response::v1::Response::Ping(v) => { + struct_ser.serialize_field("ping", v)?; + } + subscribe_response::v1::Response::Pong(v) => { + struct_ser.serialize_field("pong", v)?; + } + subscribe_response::v1::Response::TopicsLive(v) => { + struct_ser.serialize_field("topics_live", v)?; + } + subscribe_response::v1::Response::CatchupComplete(v) => { + struct_ser.serialize_field("catchup_complete", v)?; + } + } + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_response::V1 { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "messages", + "started", + "ping", + "pong", + "topics_live", + "topicsLive", + "catchup_complete", + "catchupComplete", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Messages, + Started, + Ping, + Pong, + TopicsLive, + CatchupComplete, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "messages" => Ok(GeneratedField::Messages), + "started" => Ok(GeneratedField::Started), + "ping" => Ok(GeneratedField::Ping), + "pong" => Ok(GeneratedField::Pong), + "topicsLive" | "topics_live" => Ok(GeneratedField::TopicsLive), + "catchupComplete" | "catchup_complete" => Ok(GeneratedField::CatchupComplete), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_response::V1; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeResponse.V1") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut response__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Messages => { + if response__.is_some() { + return Err(serde::de::Error::duplicate_field("messages")); + } + response__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_response::v1::Response::Messages) +; + } + GeneratedField::Started => { + if response__.is_some() { + return Err(serde::de::Error::duplicate_field("started")); + } + response__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_response::v1::Response::Started) +; + } + GeneratedField::Ping => { + if response__.is_some() { + return Err(serde::de::Error::duplicate_field("ping")); + } + response__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_response::v1::Response::Ping) +; + } + GeneratedField::Pong => { + if response__.is_some() { + return Err(serde::de::Error::duplicate_field("pong")); + } + response__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_response::v1::Response::Pong) +; + } + GeneratedField::TopicsLive => { + if response__.is_some() { + return Err(serde::de::Error::duplicate_field("topicsLive")); + } + response__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_response::v1::Response::TopicsLive) +; + } + GeneratedField::CatchupComplete => { + if response__.is_some() { + return Err(serde::de::Error::duplicate_field("catchupComplete")); + } + response__ = map_.next_value::<::std::option::Option<_>>()?.map(subscribe_response::v1::Response::CatchupComplete) +; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_response::V1 { + response: response__, + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_response::v1::Capability { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + let variant = match self { + Self::Unspecified => "CAPABILITY_UNSPECIFIED", + }; + serializer.serialize_str(variant) + } +} +impl<'de> serde::Deserialize<'de> for subscribe_response::v1::Capability { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "CAPABILITY_UNSPECIFIED", + ]; + + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> for GeneratedVisitor { + type Value = subscribe_response::v1::Capability; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + fn visit_i64(self, v: i64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Signed(v), &self) + }) + } + + fn visit_u64(self, v: u64) -> std::result::Result + where + E: serde::de::Error, + { + i32::try_from(v) + .ok() + .and_then(|x| x.try_into().ok()) + .ok_or_else(|| { + serde::de::Error::invalid_value(serde::de::Unexpected::Unsigned(v), &self) + }) + } + + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "CAPABILITY_UNSPECIFIED" => Ok(subscribe_response::v1::Capability::Unspecified), + _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), + } + } + } + deserializer.deserialize_any(GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_response::v1::CatchupComplete { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.mutate_id != 0 { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.CatchupComplete", len)?; + if self.mutate_id != 0 { + #[allow(clippy::needless_borrow)] + #[allow(clippy::needless_borrows_for_generic_args)] + struct_ser.serialize_field("mutate_id", ToString::to_string(&self.mutate_id).as_str())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_response::v1::CatchupComplete { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "mutate_id", + "mutateId", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + MutateId, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "mutateId" | "mutate_id" => Ok(GeneratedField::MutateId), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_response::v1::CatchupComplete; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeResponse.V1.CatchupComplete") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut mutate_id__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::MutateId => { + if mutate_id__.is_some() { + return Err(serde::de::Error::duplicate_field("mutateId")); + } + mutate_id__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_response::v1::CatchupComplete { + mutate_id: mutate_id__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.CatchupComplete", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_response::v1::Messages { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.group_messages.is_empty() { + len += 1; + } + if !self.welcome_messages.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.Messages", len)?; + if !self.group_messages.is_empty() { + struct_ser.serialize_field("group_messages", &self.group_messages)?; + } + if !self.welcome_messages.is_empty() { + struct_ser.serialize_field("welcome_messages", &self.welcome_messages)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_response::v1::Messages { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "group_messages", + "groupMessages", + "welcome_messages", + "welcomeMessages", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + GroupMessages, + WelcomeMessages, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "groupMessages" | "group_messages" => Ok(GeneratedField::GroupMessages), + "welcomeMessages" | "welcome_messages" => Ok(GeneratedField::WelcomeMessages), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_response::v1::Messages; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeResponse.V1.Messages") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut group_messages__ = None; + let mut welcome_messages__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::GroupMessages => { + if group_messages__.is_some() { + return Err(serde::de::Error::duplicate_field("groupMessages")); + } + group_messages__ = Some(map_.next_value()?); + } + GeneratedField::WelcomeMessages => { + if welcome_messages__.is_some() { + return Err(serde::de::Error::duplicate_field("welcomeMessages")); + } + welcome_messages__ = Some(map_.next_value()?); + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_response::v1::Messages { + group_messages: group_messages__.unwrap_or_default(), + welcome_messages: welcome_messages__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.Messages", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_response::v1::Started { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if self.keepalive_interval_ms != 0 { + len += 1; + } + if !self.capabilities.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.Started", len)?; + if self.keepalive_interval_ms != 0 { + struct_ser.serialize_field("keepalive_interval_ms", &self.keepalive_interval_ms)?; + } + if !self.capabilities.is_empty() { + let v = self.capabilities.iter().cloned().map(|v| { + subscribe_response::v1::Capability::try_from(v) + .map_err(|_| serde::ser::Error::custom(format!("Invalid variant {}", v))) + }).collect::, _>>()?; + struct_ser.serialize_field("capabilities", &v)?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_response::v1::Started { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "keepalive_interval_ms", + "keepaliveIntervalMs", + "capabilities", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + KeepaliveIntervalMs, + Capabilities, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "keepaliveIntervalMs" | "keepalive_interval_ms" => Ok(GeneratedField::KeepaliveIntervalMs), + "capabilities" => Ok(GeneratedField::Capabilities), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_response::v1::Started; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeResponse.V1.Started") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut keepalive_interval_ms__ = None; + let mut capabilities__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::KeepaliveIntervalMs => { + if keepalive_interval_ms__.is_some() { + return Err(serde::de::Error::duplicate_field("keepaliveIntervalMs")); + } + keepalive_interval_ms__ = + Some(map_.next_value::<::pbjson::private::NumberDeserialize<_>>()?.0) + ; + } + GeneratedField::Capabilities => { + if capabilities__.is_some() { + return Err(serde::de::Error::duplicate_field("capabilities")); + } + capabilities__ = Some(map_.next_value::>()?.into_iter().map(|x| x as i32).collect()); + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_response::v1::Started { + keepalive_interval_ms: keepalive_interval_ms__.unwrap_or_default(), + capabilities: capabilities__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.Started", FIELDS, GeneratedVisitor) + } +} +impl serde::Serialize for subscribe_response::v1::TopicsLive { + #[allow(deprecated)] + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + use serde::ser::SerializeStruct; + let mut len = 0; + if !self.topics.is_empty() { + len += 1; + } + let mut struct_ser = serializer.serialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.TopicsLive", len)?; + if !self.topics.is_empty() { + struct_ser.serialize_field("topics", &self.topics.iter().map(pbjson::private::base64::encode).collect::>())?; + } + struct_ser.end() + } +} +impl<'de> serde::Deserialize<'de> for subscribe_response::v1::TopicsLive { + #[allow(deprecated)] + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + const FIELDS: &[&str] = &[ + "topics", + ]; + + #[allow(clippy::enum_variant_names)] + enum GeneratedField { + Topics, + __SkipField__, + } + impl<'de> serde::Deserialize<'de> for GeneratedField { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + struct GeneratedVisitor; + + impl serde::de::Visitor<'_> for GeneratedVisitor { + type Value = GeneratedField; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "expected one of: {:?}", &FIELDS) + } + + #[allow(unused_variables)] + fn visit_str(self, value: &str) -> std::result::Result + where + E: serde::de::Error, + { + match value { + "topics" => Ok(GeneratedField::Topics), + _ => Ok(GeneratedField::__SkipField__), + } + } + } + deserializer.deserialize_identifier(GeneratedVisitor) + } + } + struct GeneratedVisitor; + impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { + type Value = subscribe_response::v1::TopicsLive; + + fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + formatter.write_str("struct xmtp.mls.api.v1.SubscribeResponse.V1.TopicsLive") + } + + fn visit_map(self, mut map_: V) -> std::result::Result + where + V: serde::de::MapAccess<'de>, + { + let mut topics__ = None; + while let Some(k) = map_.next_key()? { + match k { + GeneratedField::Topics => { + if topics__.is_some() { + return Err(serde::de::Error::duplicate_field("topics")); + } + topics__ = + Some(map_.next_value::>>()? + .into_iter().map(|x| x.0).collect()) + ; + } + GeneratedField::__SkipField__ => { + let _ = map_.next_value::()?; + } + } + } + Ok(subscribe_response::v1::TopicsLive { + topics: topics__.unwrap_or_default(), + }) + } + } + deserializer.deserialize_struct("xmtp.mls.api.v1.SubscribeResponse.V1.TopicsLive", FIELDS, GeneratedVisitor) + } +} impl serde::Serialize for SubscribeWelcomeMessagesRequest { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result