Skip to main content

hypercore_protocol/
schema.rs

1use compact_encoding::{
2    CompactEncoding, EncodingError, map_decode, map_encode, sum_encoded_size, take_array,
3    take_array_mut, write_array, write_slice,
4};
5use hypercore_schema::{
6    DataBlock, DataHash, DataSeek, DataUpgrade, Proof, RequestBlock, RequestSeek, RequestUpgrade,
7};
8use tracing::instrument;
9
10/// Open message
11#[derive(Debug, Clone, PartialEq)]
12pub struct Open {
13    /// Channel id to open
14    pub channel: u64,
15    /// Protocol name
16    pub protocol: String,
17    /// Hypercore discovery key
18    pub discovery_key: Vec<u8>,
19    /// Capability hash
20    pub capability: Option<Vec<u8>>,
21}
22
23impl CompactEncoding for Open {
24    #[instrument(skip_all, ret, err)]
25    fn encoded_size(&self) -> Result<usize, EncodingError> {
26        let out = sum_encoded_size!(self.channel, self.protocol, self.discovery_key);
27        if self.capability.is_some() {
28            return Ok(
29                out
30                    + 1  // flags for future use
31                    + 32, // TODO capabalilities buff should always be 32 bytes, but it's a vec
32            );
33        }
34        Ok(out)
35    }
36
37    #[instrument(skip_all)]
38    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
39        let rest = map_encode!(buffer, self.channel, self.protocol, self.discovery_key);
40        if let Some(cap) = &self.capability {
41            let (_, rest) = take_array_mut::<1>(rest)?;
42            return write_slice(cap, rest);
43        }
44        Ok(rest)
45    }
46
47    #[instrument(skip_all, err)]
48    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
49    where
50        Self: Sized,
51    {
52        let ((channel, protocol, discovery_key), rest) =
53            map_decode!(buffer, [u64, String, Vec<u8>]);
54        // NB: Open/Close are only sent alone in their own Frame. So we're done when there is no
55        // more data
56        let (capability, rest) = if !rest.is_empty() {
57            let (_, rest) = take_array::<1>(rest)?;
58            let (capability, rest) = take_array::<32>(rest)?;
59            (Some(capability.to_vec()), rest)
60        } else {
61            (None, rest)
62        };
63        Ok((
64            Self {
65                channel,
66                protocol,
67                discovery_key,
68                capability,
69            },
70            rest,
71        ))
72    }
73}
74
75/// Close message
76#[derive(Debug, Clone, PartialEq)]
77pub struct Close {
78    /// Channel id to close
79    pub channel: u64,
80}
81
82impl CompactEncoding for Close {
83    fn encoded_size(&self) -> Result<usize, EncodingError> {
84        self.channel.encoded_size()
85    }
86
87    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
88        self.channel.encode(buffer)
89    }
90
91    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
92    where
93        Self: Sized,
94    {
95        let (channel, rest) = u64::decode(buffer)?;
96        Ok((Self { channel }, rest))
97    }
98}
99
100/// Synchronize message. Type 0.
101#[derive(Debug, Clone, PartialEq)]
102pub struct Synchronize {
103    /// Fork id, set to 0 for an un-forked hypercore.
104    pub fork: u64,
105    /// Length of hypercore
106    pub length: u64,
107    /// Known length of the remote party, 0 for unknown.
108    pub remote_length: u64,
109    /// Downloading allowed
110    pub downloading: bool,
111    /// Uploading allowed
112    pub uploading: bool,
113    /// Upgrade possible
114    pub can_upgrade: bool,
115}
116
117impl CompactEncoding for Synchronize {
118    fn encoded_size(&self) -> Result<usize, EncodingError> {
119        Ok(1 + sum_encoded_size!(self.fork, self.length, self.remote_length))
120    }
121
122    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
123        let mut flags: u8 = if self.can_upgrade { 1 } else { 0 };
124        flags |= if self.uploading { 2 } else { 0 };
125        flags |= if self.downloading { 4 } else { 0 };
126        let rest = write_array(&[flags], buffer)?;
127        Ok(map_encode!(
128            rest,
129            self.fork,
130            self.length,
131            self.remote_length
132        ))
133    }
134
135    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
136    where
137        Self: Sized,
138    {
139        let ([flags], rest) = take_array::<1>(buffer)?;
140        let ((fork, length, remote_length), rest) = map_decode!(rest, [u64, u64, u64]);
141        let can_upgrade = flags & 1 != 0;
142        let uploading = flags & 2 != 0;
143        let downloading = flags & 4 != 0;
144        Ok((
145            Synchronize {
146                fork,
147                length,
148                remote_length,
149                can_upgrade,
150                uploading,
151                downloading,
152            },
153            rest,
154        ))
155    }
156}
157
158/// Request message. Type 1.
159#[derive(Debug, Clone, PartialEq)]
160pub struct Request {
161    /// Request id, will be returned with corresponding [Data]
162    pub id: u64,
163    /// Current fork, set to 0 for un-forked hypercore
164    pub fork: u64,
165    /// Request for data
166    pub block: Option<RequestBlock>,
167    /// Request hash
168    pub hash: Option<RequestBlock>,
169    /// Request seek
170    pub seek: Option<RequestSeek>,
171    /// Request upgrade
172    pub upgrade: Option<RequestUpgrade>,
173    // TODO what is this
174    /// Request manifest
175    pub manifest: bool,
176    // TODO what is this
177    // this could prob be usize
178    /// Request priority
179    pub priority: u64,
180}
181
182macro_rules! maybe_decode {
183    ($cond:expr, $type:ty, $buf:ident) => {
184        if $cond {
185            let (result, rest) = <$type>::decode($buf)?;
186            (Some(result), rest)
187        } else {
188            (None, $buf)
189        }
190    };
191}
192
193impl CompactEncoding for Request {
194    fn encoded_size(&self) -> Result<usize, EncodingError> {
195        let mut out = 1; // flags
196        out += sum_encoded_size!(self.id, self.fork);
197        if let Some(block) = &self.block {
198            out += block.encoded_size()?;
199        }
200        if let Some(hash) = &self.hash {
201            out += hash.encoded_size()?;
202        }
203        if let Some(seek) = &self.seek {
204            out += seek.encoded_size()?;
205        }
206        if let Some(upgrade) = &self.upgrade {
207            out += upgrade.encoded_size()?;
208        }
209        if self.priority != 0 {
210            out += self.priority.encoded_size()?;
211        }
212        Ok(out)
213    }
214
215    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
216        let mut flags: u8 = if self.block.is_some() { 1 } else { 0 };
217        flags |= if self.hash.is_some() { 2 } else { 0 };
218        flags |= if self.seek.is_some() { 4 } else { 0 };
219        flags |= if self.upgrade.is_some() { 8 } else { 0 };
220        flags |= if self.manifest { 16 } else { 0 };
221        flags |= if self.priority != 0 { 32 } else { 0 };
222        let mut rest = write_array(&[flags], buffer)?;
223        rest = map_encode!(rest, self.id, self.fork);
224
225        if let Some(block) = &self.block {
226            rest = block.encode(rest)?;
227        }
228        if let Some(hash) = &self.hash {
229            rest = hash.encode(rest)?;
230        }
231        if let Some(seek) = &self.seek {
232            rest = seek.encode(rest)?;
233        }
234        if let Some(upgrade) = &self.upgrade {
235            rest = upgrade.encode(rest)?;
236        }
237
238        if self.priority != 0 {
239            rest = self.priority.encode(rest)?;
240        }
241
242        Ok(rest)
243    }
244
245    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
246    where
247        Self: Sized,
248    {
249        let ([flags], rest) = take_array::<1>(buffer)?;
250        let ((id, fork), rest) = map_decode!(rest, [u64, u64]);
251
252        let (block, rest) = maybe_decode!(flags & 1 != 0, RequestBlock, rest);
253        let (hash, rest) = maybe_decode!(flags & 2 != 0, RequestBlock, rest);
254        let (seek, rest) = maybe_decode!(flags & 4 != 0, RequestSeek, rest);
255        let (upgrade, rest) = maybe_decode!(flags & 8 != 0, RequestUpgrade, rest);
256        let manifest = flags & 16 != 0;
257        let (priority, rest) = if flags & 32 != 0 {
258            u64::decode(rest)?
259        } else {
260            (0, rest)
261        };
262        Ok((
263            Request {
264                id,
265                fork,
266                block,
267                hash,
268                seek,
269                upgrade,
270                manifest,
271                priority,
272            },
273            rest,
274        ))
275    }
276}
277
278/// Cancel message for a [Request]. Type 2
279#[derive(Debug, Clone, PartialEq)]
280pub struct Cancel {
281    /// Request to cancel, see field `id` in [Request]
282    pub request: u64,
283}
284
285impl CompactEncoding for Cancel {
286    fn encoded_size(&self) -> Result<usize, EncodingError> {
287        self.request.encoded_size()
288    }
289
290    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
291        self.request.encode(buffer)
292    }
293
294    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
295    where
296        Self: Sized,
297    {
298        let (request, rest) = u64::decode(buffer)?;
299        Ok((Cancel { request }, rest))
300    }
301}
302
303/// Data message responding to received [Request]. Type 3.
304#[derive(Debug, Clone, PartialEq)]
305pub struct Data {
306    /// Request this data is for, see field `id` in [Request]
307    pub request: u64,
308    /// Fork id, set to 0 for un-forked hypercore
309    pub fork: u64,
310    /// Response for block request
311    pub block: Option<DataBlock>,
312    /// Response for hash request
313    pub hash: Option<DataHash>,
314    /// Response for seek request
315    pub seek: Option<DataSeek>,
316    /// Response for upgrade request
317    pub upgrade: Option<DataUpgrade>,
318}
319
320macro_rules! opt_encoded_size {
321    ($opt:expr, $sum:ident) => {
322        if let Some(thing) = $opt {
323            $sum += thing.encoded_size()?;
324        }
325    };
326}
327
328// TODO we could write a macro where it takes a $cond that returns an opt.
329// if the option is Some(T) then do T::encode(buf)
330// also if some add $flag.
331// This would simplify some of these impls
332macro_rules! opt_encoded_bytes {
333    ($opt:expr, $buf:ident) => {
334        if let Some(thing) = $opt {
335            thing.encode($buf)?
336        } else {
337            $buf
338        }
339    };
340}
341impl CompactEncoding for Data {
342    fn encoded_size(&self) -> Result<usize, EncodingError> {
343        let mut out = 1; // flags
344        out += sum_encoded_size!(self.request, self.fork);
345        opt_encoded_size!(&self.block, out);
346        opt_encoded_size!(&self.hash, out);
347        opt_encoded_size!(&self.seek, out);
348        opt_encoded_size!(&self.upgrade, out);
349        Ok(out)
350    }
351
352    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
353        let mut flags: u8 = if self.block.is_some() { 1 } else { 0 };
354        flags |= if self.hash.is_some() { 2 } else { 0 };
355        flags |= if self.seek.is_some() { 4 } else { 0 };
356        flags |= if self.upgrade.is_some() { 8 } else { 0 };
357        let rest = write_array(&[flags], buffer)?;
358        let rest = map_encode!(rest, self.request, self.fork);
359
360        let rest = opt_encoded_bytes!(&self.block, rest);
361        let rest = opt_encoded_bytes!(&self.hash, rest);
362        let rest = opt_encoded_bytes!(&self.seek, rest);
363        let rest = opt_encoded_bytes!(&self.upgrade, rest);
364        Ok(rest)
365    }
366
367    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
368    where
369        Self: Sized,
370    {
371        let ([flags], rest) = take_array::<1>(buffer)?;
372        let ((request, fork), rest) = map_decode!(rest, [u64, u64]);
373        let (block, rest) = maybe_decode!(flags & 1 != 0, DataBlock, rest);
374        let (hash, rest) = maybe_decode!(flags & 2 != 0, DataHash, rest);
375        let (seek, rest) = maybe_decode!(flags & 4 != 0, DataSeek, rest);
376        let (upgrade, rest) = maybe_decode!(flags & 8 != 0, DataUpgrade, rest);
377        Ok((
378            Data {
379                request,
380                fork,
381                block,
382                hash,
383                seek,
384                upgrade,
385            },
386            rest,
387        ))
388    }
389}
390
391impl Data {
392    /// Transform Data message into a [`Proof`]
393    pub fn into_proof(self) -> Proof {
394        Proof {
395            fork: self.fork,
396            block: self.block,
397            hash: self.hash,
398            seek: self.seek,
399            upgrade: self.upgrade,
400        }
401    }
402}
403
404/// No data message. Type 4.
405#[derive(Debug, Clone, PartialEq)]
406pub struct NoData {
407    /// Request this message is for, see field `id` in [Request]
408    pub request: u64,
409}
410
411impl CompactEncoding for NoData {
412    fn encoded_size(&self) -> Result<usize, EncodingError> {
413        Ok(sum_encoded_size!(self.request))
414    }
415
416    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
417        Ok(map_encode!(buffer, self.request))
418    }
419
420    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
421    where
422        Self: Sized,
423    {
424        let (request, rest) = u64::decode(buffer)?;
425        Ok((Self { request }, rest))
426    }
427}
428
429/// Want message. Type 5.
430#[derive(Debug, Clone, PartialEq)]
431pub struct Want {
432    /// Start index
433    pub start: u64,
434    /// Length
435    pub length: u64,
436}
437
438impl CompactEncoding for Want {
439    fn encoded_size(&self) -> Result<usize, EncodingError> {
440        Ok(sum_encoded_size!(self.start, self.length))
441    }
442
443    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
444        Ok(map_encode!(buffer, self.start, self.length))
445    }
446
447    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
448    where
449        Self: Sized,
450    {
451        let ((start, length), rest) = map_decode!(buffer, [u64, u64]);
452        Ok((Self { start, length }, rest))
453    }
454}
455
456/// Un-want message. Type 6.
457#[derive(Debug, Clone, PartialEq)]
458pub struct Unwant {
459    /// Start index
460    pub start: u64,
461    /// Length
462    pub length: u64,
463}
464
465impl CompactEncoding for Unwant {
466    fn encoded_size(&self) -> Result<usize, EncodingError> {
467        Ok(sum_encoded_size!(self.start, self.length))
468    }
469
470    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
471        Ok(map_encode!(buffer, self.start, self.length))
472    }
473
474    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
475    where
476        Self: Sized,
477    {
478        let ((start, length), rest) = map_decode!(buffer, [u64, u64]);
479        Ok((Self { start, length }, rest))
480    }
481}
482
483/// Bitfield message. Type 7.
484#[derive(Debug, Clone, PartialEq)]
485pub struct Bitfield {
486    /// Start index of bitfield
487    pub start: u64,
488    /// Bitfield in 32 bit chunks beginning from `start`
489    pub bitfield: Vec<u32>,
490}
491impl CompactEncoding for Bitfield {
492    fn encoded_size(&self) -> Result<usize, EncodingError> {
493        Ok(sum_encoded_size!(self.start, self.bitfield))
494    }
495
496    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
497        Ok(map_encode!(buffer, self.start, self.bitfield))
498    }
499
500    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
501    where
502        Self: Sized,
503    {
504        let ((start, bitfield), rest) = map_decode!(buffer, [u64, Vec<u32>]);
505        Ok((Self { start, bitfield }, rest))
506    }
507}
508
509/// Range message. Type 8.
510/// Notifies Peer's that the Sender has a range of contiguous blocks.
511#[derive(Debug, Clone, PartialEq)]
512pub struct Range {
513    /// If true, notifies that data has been cleared from this range.
514    /// If false, notifies existing data range.
515    pub drop: bool,
516    /// Range starts at this index
517    pub start: u64,
518    /// Length of the range
519    pub length: u64,
520}
521
522impl CompactEncoding for Range {
523    fn encoded_size(&self) -> Result<usize, EncodingError> {
524        let mut out = 1 + sum_encoded_size!(self.start);
525        if self.length != 1 {
526            out += self.length.encoded_size()?;
527        }
528        Ok(out)
529    }
530
531    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
532        let mut flags: u8 = if self.drop { 1 } else { 0 };
533        flags |= if self.length == 1 { 2 } else { 0 };
534        let rest = write_array(&[flags], buffer)?;
535        let rest = self.start.encode(rest)?;
536        if self.length != 1 {
537            return self.length.encode(rest);
538        }
539        Ok(rest)
540    }
541
542    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
543    where
544        Self: Sized,
545    {
546        let ([flags], rest) = take_array::<1>(buffer)?;
547        let (start, rest) = u64::decode(rest)?;
548        let drop = flags & 1 != 0;
549        let (length, rest) = if flags & 2 != 0 {
550            (1, rest)
551        } else {
552            u64::decode(rest)?
553        };
554        Ok((
555            Range {
556                drop,
557                length,
558                start,
559            },
560            rest,
561        ))
562    }
563}
564
565/// Extension message. Type 9. Use this for custom messages in your application.
566#[derive(Debug, Clone, PartialEq)]
567pub struct Extension {
568    /// Name of the custom message
569    pub name: String,
570    /// Message content, use empty vector for no data.
571    pub message: Vec<u8>,
572}
573impl CompactEncoding for Extension {
574    fn encoded_size(&self) -> Result<usize, EncodingError> {
575        Ok(sum_encoded_size!(self.name, self.message))
576    }
577
578    fn encode<'a>(&self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], EncodingError> {
579        Ok(map_encode!(buffer, self.name, self.message))
580    }
581
582    fn decode(buffer: &[u8]) -> Result<(Self, &[u8]), EncodingError>
583    where
584        Self: Sized,
585    {
586        let ((name, message), rest) = map_decode!(buffer, [String, Vec<u8>]);
587        Ok((Self { name, message }, rest))
588    }
589}