1use core::fmt::{self, Display, Formatter};
13use core::str::FromStr;
14use std::borrow::{Borrow, BorrowMut};
15use std::io;
16use std::ops::{Deref, DerefMut};
17
18use bitcoin::util::bip32;
19use strict_encoding::{StrictDecode, StrictEncode};
20
21use crate::SegmentIndexes;
22
23#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, From)]
30#[cfg_attr(
31 feature = "serde",
32 derive(Serialize, Deserialize),
33 serde(crate = "serde_crate")
34)]
35pub struct DerivationSubpath<Segment>(Vec<Segment>)
36where
37 Segment: SegmentIndexes;
38
39impl<Segment> Deref for DerivationSubpath<Segment>
41where
42 Segment: SegmentIndexes,
43{
44 type Target = Vec<Segment>;
45
46 fn deref(&self) -> &Self::Target { &self.0 }
47}
48
49impl<Segment> DerefMut for DerivationSubpath<Segment>
50where
51 Segment: SegmentIndexes,
52{
53 fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
54}
55
56impl<Segment> Default for DerivationSubpath<Segment>
57where
58 Segment: SegmentIndexes,
59{
60 fn default() -> Self { Self(vec![]) }
61}
62
63impl<Segment> From<&[Segment]> for DerivationSubpath<Segment>
64where
65 Segment: SegmentIndexes,
66{
67 fn from(path: &[Segment]) -> Self { Self(path.to_vec()) }
68}
69
70impl<Segment> AsRef<[Segment]> for DerivationSubpath<Segment>
71where
72 Segment: SegmentIndexes,
73{
74 #[inline]
75 fn as_ref(&self) -> &[Segment] { &self.0 }
76}
77
78impl<Segment> AsMut<Vec<Segment>> for DerivationSubpath<Segment>
79where
80 Segment: SegmentIndexes,
81{
82 #[inline]
83 fn as_mut(&mut self) -> &mut Vec<Segment> { &mut self.0 }
84}
85
86impl<Segment> Borrow<[Segment]> for DerivationSubpath<Segment>
87where
88 Segment: SegmentIndexes,
89{
90 #[inline]
91 fn borrow(&self) -> &[Segment] { &self.0 }
92}
93
94impl<Segment> BorrowMut<[Segment]> for DerivationSubpath<Segment>
95where
96 Segment: SegmentIndexes,
97{
98 #[inline]
99 fn borrow_mut(&mut self) -> &mut [Segment] { &mut self.0 }
100}
101
102impl<Segment> StrictEncode for DerivationSubpath<Segment>
103where
104 Segment: SegmentIndexes + StrictEncode,
105{
106 #[inline]
107 fn strict_encode<E: io::Write>(&self, e: E) -> Result<usize, strict_encoding::Error> {
108 self.0.strict_encode(e)
109 }
110}
111
112impl<Segment> StrictDecode for DerivationSubpath<Segment>
113where
114 Segment: SegmentIndexes + StrictDecode,
115{
116 #[inline]
117 fn strict_decode<D: io::Read>(d: D) -> Result<Self, strict_encoding::Error> {
118 Ok(Self(Vec::strict_decode(d)?))
119 }
120}
121
122impl<Segment> Display for DerivationSubpath<Segment>
123where
124 Segment: SegmentIndexes + Display,
125{
126 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
127 for segment in &self.0 {
128 f.write_str("/")?;
129 Display::fmt(segment, f)?;
130 }
131 Ok(())
132 }
133}
134
135impl<Segment> FromStr for DerivationSubpath<Segment>
136where
137 Segment: SegmentIndexes + FromStr,
138 bip32::Error: From<<Segment as FromStr>::Err>,
139{
140 type Err = bip32::Error;
141
142 fn from_str(s: &str) -> Result<Self, Self::Err> {
143 if !s.starts_with('/') {
144 return Err(bip32::Error::InvalidDerivationPathFormat);
145 }
146 let inner = s[1..]
147 .split('/')
148 .map(Segment::from_str)
149 .collect::<Result<Vec<_>, Segment::Err>>()?;
150 if inner.is_empty() {
151 return Err(bip32::Error::InvalidDerivationPathFormat);
152 }
153 Ok(Self(inner))
154 }
155}
156
157impl<Segment> IntoIterator for DerivationSubpath<Segment>
158where
159 Segment: SegmentIndexes,
160{
161 type Item = Segment;
162 type IntoIter = std::vec::IntoIter<Segment>;
163
164 fn into_iter(self) -> Self::IntoIter { self.0.into_iter() }
165}
166
167impl<'path, Segment> IntoIterator for &'path DerivationSubpath<Segment>
168where
169 Segment: SegmentIndexes + Copy,
170{
171 type Item = Segment;
172 type IntoIter = std::iter::Copied<std::slice::Iter<'path, Segment>>;
173
174 fn into_iter(self) -> Self::IntoIter { self.0.iter().copied() }
175}
176
177impl<Segment> FromIterator<Segment> for DerivationSubpath<Segment>
178where
179 Segment: SegmentIndexes,
180{
181 fn from_iter<T: IntoIterator<Item = Segment>>(iter: T) -> Self {
182 Self(iter.into_iter().collect())
183 }
184}
185
186impl<Segment> DerivationSubpath<Segment>
187where
188 Segment: SegmentIndexes,
189{
190 pub fn new() -> Self { Self::default() }
192}