willow_data_model/private_encodings/
path.rs1#[cfg(feature = "dev")]
2use arbitrary::Arbitrary;
3use compact_u64::CompactU64;
4use ufotofu_codec::{
5 Blame, Decodable, DecodeError, Encodable, RelativeDecodable, RelativeEncodable,
6};
7
8use crate::{decode_path_extends_path, encode_path_extends_path, Path};
9
10#[derive(Debug)]
11pub struct PrivatePathContext<const MCL: usize, const MCC: usize, const MPL: usize> {
13 private: Path<MCL, MCC, MPL>,
15 rel: Path<MCL, MCC, MPL>,
17}
18
19#[derive(Debug)]
20pub struct ComponentsNotRelatedError {}
21
22impl<const MCL: usize, const MCC: usize, const MPL: usize> PrivatePathContext<MCL, MCC, MPL> {
23 pub fn new(
24 private: Path<MCL, MCC, MPL>,
25 rel: Path<MCL, MCC, MPL>,
26 ) -> Result<Self, ComponentsNotRelatedError> {
27 if !private.is_related(&rel) {
28 return Err(ComponentsNotRelatedError {});
29 }
30
31 Ok(Self { private, rel })
32 }
33
34 pub fn new_unchecked(private: Path<MCL, MCC, MPL>, rel: Path<MCL, MCC, MPL>) -> Self {
35 Self { private, rel }
36 }
37
38 pub fn private(&self) -> &Path<MCL, MCC, MPL> {
39 &self.private
40 }
41
42 pub fn rel(&self) -> &Path<MCL, MCC, MPL> {
43 &self.rel
44 }
45}
46
47#[cfg(feature = "dev")]
48impl<'a, const MCL: usize, const MCC: usize, const MPL: usize> Arbitrary<'a>
49 for PrivatePathContext<MCL, MCC, MPL>
50{
51 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
52 let private: Path<MCL, MCC, MPL> = Arbitrary::arbitrary(u)?;
53 let rel: Path<MCL, MCC, MPL> = Arbitrary::arbitrary(u)?;
54
55 Ok(Self { private, rel })
56 }
57}
58
59impl<const MCL: usize, const MCC: usize, const MPL: usize>
60 RelativeEncodable<PrivatePathContext<MCL, MCC, MPL>> for Path<MCL, MCC, MPL>
61{
62 async fn relative_encode<C>(
63 &self,
64 consumer: &mut C,
65 r: &PrivatePathContext<MCL, MCC, MPL>,
66 ) -> Result<(), C::Error>
67 where
68 C: ufotofu::BulkConsumer<Item = u8>,
69 {
70 if !r.rel.is_prefix_of(self) {
71 panic!("Tried to encode a path relative to a PrivatePathContext.rel path it is not prefixed by")
72 }
73
74 if !self.is_related(&r.private) {
75 panic!("Tried to encode a path relative to a PrivatePathContext.private pat it is not related to")
76 }
77
78 let rel_count = r.rel.component_count();
79 let private_count = r.private.component_count();
80
81 if private_count <= rel_count {
82 encode_path_extends_path(consumer, self, &r.rel).await?;
84 } else {
85 let lcp = self.longest_common_prefix(&r.private);
86
87 let lcp_len = lcp.component_count();
88 CompactU64(lcp.component_count() as u64)
89 .encode(consumer)
90 .await?;
91
92 if lcp_len >= private_count {
93 encode_path_extends_path(consumer, self, r.private()).await?;
95 }
96 }
97
98 Ok(())
99 }
100}
101
102impl<const MCL: usize, const MCC: usize, const MPL: usize>
103 RelativeDecodable<PrivatePathContext<MCL, MCC, MPL>, Blame> for Path<MCL, MCC, MPL>
104{
105 async fn relative_decode<P>(
106 producer: &mut P,
107 r: &PrivatePathContext<MCL, MCC, MPL>,
108 ) -> Result<Self, DecodeError<P::Final, P::Error, Blame>>
109 where
110 P: ufotofu::BulkProducer<Item = u8>,
111 Self: Sized,
112 {
113 let rel_count = r.rel.component_count();
114 let private_count = r.private.component_count();
115
116 if private_count <= rel_count {
117 decode_path_extends_path(producer, r.rel()).await
118 } else {
119 let private_component_count = CompactU64::decode(producer)
121 .await
122 .map_err(DecodeError::map_other_from)?;
123
124 if private_component_count.0 >= private_count as u64 {
125 decode_path_extends_path(producer, r.private()).await
126 } else {
127 r.private
129 .create_prefix(private_component_count.0 as usize)
130 .ok_or(DecodeError::Other(Blame::TheirFault))
131 }
132 }
133 }
134}