1use std::{fmt, iter};
7use bytes::BufMut;
8use ::bits::compose::{Compose, Compress, Compressor};
9use ::bits::parse::ShortBuf;
10use super::label::Label;
11use super::relative::DnameIter;
12use super::traits::{ToLabelIter, ToRelativeDname, ToDname};
13use super::uncertain::UncertainDname;
14
15
16#[derive(Clone, Debug)]
36pub struct Chain<L, R> {
37    left: L,
39
40    right: R,
42}
43
44impl<L: Compose, R: Compose> Chain<L, R> {
45    pub(super) fn new(left: L, right: R) -> Result<Self, LongChainError> {
47        if left.compose_len() + right.compose_len() > 255 {
48            Err(LongChainError)
49        }
50        else {
51            Ok(Chain { left, right })
52        }
53    }
54}
55
56impl<R: Compose> Chain<UncertainDname, R> {
57    pub(super) fn new_uncertain(left: UncertainDname, right: R)
62                                -> Result<Self, LongChainError> {
63        if let UncertainDname::Relative(ref name) = left {
64            if name.compose_len() + right.compose_len() > 255 {
65                return Err(LongChainError)
66            }
67        }
68        Ok(Chain { left, right })
69    }
70}
71
72impl<L: ToRelativeDname, R: Compose> Chain<L, R> {
73    pub fn chain<N: Compose>(self, other: N)
87                                -> Result<Chain<Self, N>, LongChainError> {
88        Chain::new(self, other)
89    }
90}
91
92impl<L, R> Chain<L, R> {
93    pub fn unwrap(self) -> (L, R) {
95        (self.left, self.right)
96    }
97}
98
99impl<'a, L: ToRelativeDname, R: for<'r> ToLabelIter<'r>> ToLabelIter<'a>
100            for Chain<L, R> {
101    type LabelIter = ChainIter<'a, L, R>;
102
103    fn iter_labels(&'a self) -> Self::LabelIter {
104        ChainIter(self.left.iter_labels().chain(self.right.iter_labels()))
105    }
106}
107
108impl<L: ToRelativeDname, R: Compose> Compose for Chain<L, R> {
109    fn compose_len(&self) -> usize {
110        self.left.compose_len() + self.right.compose_len()
111    }
112
113    fn compose<B: BufMut>(&self, buf: &mut B) {
114        self.left.compose(buf);
115        self.right.compose(buf)
116    }
117}
118
119impl<L: ToRelativeDname, R: ToDname> Compress for Chain<L, R> {
120    fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
121        buf.compress_name(self)
122    }
123}
124
125impl<L: ToRelativeDname, R: ToRelativeDname> ToRelativeDname for Chain<L, R> {
126}
127
128impl<L: ToRelativeDname, R: ToDname> ToDname for Chain<L, R> {
129}
130
131impl<L: fmt::Display, R: fmt::Display> fmt::Display for Chain<L, R> {
132    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
133        write!(f, "{}.{}", self.left, self.right)
134    }
135}
136
137impl<'a, R: ToDname> ToLabelIter<'a> for Chain<UncertainDname, R> {
138    type LabelIter = UncertainChainIter<'a, R>;
139
140    fn iter_labels(&'a self) -> Self::LabelIter {
141        match self.left {
142            UncertainDname::Absolute(ref name) => {
143                UncertainChainIter::Absolute(name.iter_labels())
144            }
145            UncertainDname::Relative(ref name) => {
146                UncertainChainIter::Relative(
147                    ChainIter(name.iter_labels()
148                                  .chain(self.right.iter_labels()))
149                )
150            }
151        }
152    }
153}
154
155impl<R: ToDname> Compose for Chain<UncertainDname, R> {
156    fn compose_len(&self) -> usize {
157        match self.left {
158            UncertainDname::Absolute(ref name) => name.compose_len(),
159            UncertainDname::Relative(ref name) => {
160                name.compose_len() + self.right.compose_len()
161            }
162        }
163    }
164
165    fn compose<B: BufMut>(&self, buf: &mut B) {
166        match self.left {
167            UncertainDname::Absolute(ref name) => name.compose(buf),
168            UncertainDname::Relative(ref name) => {
169                name.compose(buf);
170                self.right.compose(buf)
171            }
172        }
173    }
174}
175
176
177impl<R: ToDname> Compress for Chain<UncertainDname, R> {
178    fn compress(&self, buf: &mut Compressor) -> Result<(), ShortBuf> {
179        if let UncertainDname::Absolute(ref name) = self.left {
180            buf.compress_name(name)
181        }
182        else {
183            buf.compress_name(self)
185        }
186    }
187}
188
189impl<R: ToDname> ToDname for Chain<UncertainDname, R> { }
190
191
192#[derive(Clone, Debug)]
196pub struct ChainIter<'a, L: ToLabelIter<'a>, R: ToLabelIter<'a>>(
197    iter::Chain<L::LabelIter, R::LabelIter>
198);
199
200impl<'a, L, R> Iterator for ChainIter<'a, L, R>
201        where L: ToLabelIter<'a>, R: ToLabelIter<'a> {
202    type Item = &'a Label;
203
204    fn next(&mut self) -> Option<Self::Item> {
205        self.0.next()
206    }
207}
208
209impl<'a, L, R> DoubleEndedIterator for ChainIter<'a, L, R>
210        where L: ToLabelIter<'a>, R: ToLabelIter<'a> {
211    fn next_back(&mut self) -> Option<Self::Item> {
212        self.0.next_back()
213    }
214}
215
216
217pub enum UncertainChainIter<'a, R: ToLabelIter<'a>> {
221    Absolute(DnameIter<'a>),
222    Relative(ChainIter<'a, UncertainDname, R>),
223}
224
225impl<'a, R> Iterator for UncertainChainIter<'a, R>
226where R: ToLabelIter<'a>
227{
228    type Item = &'a Label;
229
230    fn next(&mut self) -> Option<Self::Item> {
231        match *self {
232            UncertainChainIter::Absolute(ref mut inner) => inner.next(),
233            UncertainChainIter::Relative(ref mut inner) => inner.next()
234        }
235    }
236}
237
238impl<'a, R> DoubleEndedIterator for UncertainChainIter<'a, R>
239where R: ToLabelIter<'a>
240{
241    fn next_back(&mut self) -> Option<Self::Item> {
242        match *self {
243            UncertainChainIter::Absolute(ref mut inner) => inner.next_back(),
244            UncertainChainIter::Relative(ref mut inner) => inner.next_back()
245        }
246    }
247}
248
249
250#[derive(Clone, Copy, Debug, Eq, Fail, PartialEq)]
254#[fail(display="long domain name")]
255pub struct LongChainError;
256
257
258#[cfg(test)]
261mod test {
262    use bytes::BytesMut;
263    use ::bits::compose::{Compose, Compress, Compressor};
264    use ::bits::name::{Dname, DnameBuilder, Label, RelativeDname, ToDname,
265                       ToLabelIter, ToRelativeDname, UncertainDname};
266
267    fn assert_to_dname<T: ToDname>(_: &T) { }
268    fn assert_to_relative_dname<T: ToRelativeDname>(_: &T) { }
269
270    #[test]
273    fn impls() {
274        let rel = RelativeDname::empty()
275                                .chain(RelativeDname::empty()).unwrap();
276        assert_to_dname(&RelativeDname::empty().chain(Dname::root()).unwrap());
277        assert_to_relative_dname(&rel);
278        assert_to_dname(&rel.clone().chain(Dname::root()).unwrap());
279        assert_to_relative_dname(&rel.chain(RelativeDname::empty()).unwrap());
280        assert_to_dname(&UncertainDname::root().chain(Dname::root()).unwrap());
281    }
282
283    #[test]
285    fn name_limit() {
286        let mut builder = DnameBuilder::new();
287        for _ in 0..25 {
288            builder.append_label(b"123456789").unwrap();
290        }
291        let left = builder.finish();
292        assert_eq!(left.len(), 250);
293
294        let mut builder = DnameBuilder::new();
295        builder.append(b"123").unwrap();
296        let five_abs = builder.clone().into_dname().unwrap();
297        assert_eq!(five_abs.len(), 5);
298        builder.push(b'4').unwrap();
299        let five_rel = builder.clone().finish();
300        assert_eq!(five_rel.len(), 5);
301        let six_abs = builder.clone().into_dname().unwrap();
302        assert_eq!(six_abs.len(), 6);
303        builder.push(b'5').unwrap();
304        let six_rel = builder.finish();
305        assert_eq!(six_rel.len(), 6);
306
307        assert_eq!(left.clone().chain(five_abs.clone())
308                       .unwrap().compose_len(),
309                   255);
310        assert_eq!(left.clone().chain(five_rel.clone())
311                       .unwrap().compose_len(),
312                   255);
313        assert!(left.clone().chain(six_abs.clone()).is_err());
314        assert!(left.clone().chain(six_rel.clone()).is_err());
315        assert!(left.clone().chain(five_rel.clone()).unwrap()
316                            .chain(five_abs.clone()).is_err());
317        assert!(left.clone().chain(five_rel.clone()).unwrap()
318                            .chain(five_rel.clone()).is_err());
319
320        let left = UncertainDname::from(left);
321        assert_eq!(left.clone().chain(five_abs.clone())
322                       .unwrap().compose_len(),
323                   255);
324        assert!(left.clone().chain(six_abs.clone()).is_err());
325
326        let left = UncertainDname::from(left.into_absolute());
327        assert_eq!(left.clone().chain(six_abs.clone())
328                       .unwrap().compose_len(),
329                   251);
330    }
331
332    fn cmp_iter<'a, I>(iter: I, labels: &[&[u8]])
333                where I: Iterator<Item=&'a Label> {
334        let labels = labels.iter().map(|s| Label::from_slice(s).unwrap());
335        assert!(iter.eq(labels))
336    }
337
338    #[test]
340    fn iter_labels() {
341        let w = RelativeDname::from_slice(b"\x03www").unwrap();
342        let ec = RelativeDname::from_slice(b"\x07example\x03com").unwrap();
343        let ecr = Dname::from_slice(b"\x07example\x03com\x00").unwrap();
344        let fbr = Dname::from_slice(b"\x03foo\x03bar\x00").unwrap();
345
346        cmp_iter(w.clone().chain(ec.clone()).unwrap().iter_labels(), 
347                 &[b"www", b"example", b"com"]);
348        cmp_iter(w.clone().chain(ecr.clone()).unwrap().iter_labels(),
349                 &[b"www", b"example", b"com", b""]);
350        cmp_iter(w.clone().chain(ec.clone()).unwrap()
351                          .chain(Dname::root()).unwrap().iter_labels(),
352                 &[b"www", b"example", b"com", b""]);
353        
354        cmp_iter(UncertainDname::from(w.clone())
355                                .chain(ecr.clone()).unwrap().iter_labels(),
356                 &[b"www", b"example", b"com", b""]);
357        cmp_iter(UncertainDname::from(ecr.clone())
358                                .chain(fbr.clone()).unwrap().iter_labels(),
359                 &[b"example", b"com", b""]);
360    }
361
362    #[test]
364    fn compose() {
365        let w = RelativeDname::from_slice(b"\x03www").unwrap();
366        let ec = RelativeDname::from_slice(b"\x07example\x03com").unwrap();
367        let ecr = Dname::from_slice(b"\x07example\x03com\x00").unwrap();
368        let fbr = Dname::from_slice(b"\x03foo\x03bar\x00").unwrap();
369
370        let mut buf = BytesMut::with_capacity(255);
371        w.clone().chain(ec.clone()).unwrap().compose(&mut buf);
372        assert_eq!(buf.freeze().as_ref(),
373                   b"\x03www\x07example\x03com");
374
375        let mut buf = BytesMut::with_capacity(255);
376        w.clone().chain(ecr.clone()).unwrap().compose(&mut buf);
377        assert_eq!(buf.freeze().as_ref(),
378                   b"\x03www\x07example\x03com\x00");
379
380        let mut buf = BytesMut::with_capacity(255);
381        w.clone().chain(ec.clone()).unwrap().chain(Dname::root()).unwrap()
382         .compose(&mut buf);
383        assert_eq!(buf.freeze().as_ref(),
384                   b"\x03www\x07example\x03com\x00");
385
386        let mut buf = BytesMut::with_capacity(255);
387        UncertainDname::from(w.clone()).chain(ecr.clone()).unwrap()
388            .compose(&mut buf);
389        assert_eq!(buf.freeze().as_ref(),
390                   b"\x03www\x07example\x03com\x00");
391
392        let mut buf = BytesMut::with_capacity(255);
393        UncertainDname::from(ecr.clone()).chain(fbr.clone()).unwrap()
394            .compose(&mut buf);
395        assert_eq!(buf.freeze().as_ref(),
396                   b"\x07example\x03com\x00");
397    }
398
399    #[test]
401    fn compress() {
402        let w = RelativeDname::from_slice(b"\x03www").unwrap();
403        let ec = RelativeDname::from_slice(b"\x07example\x03com").unwrap();
404        let ecr = Dname::from_slice(b"\x07example\x03com\x00").unwrap();
405        let fbr = Dname::from_slice(b"\x03foo\x03bar\x00").unwrap();
406
407        let mut buf = Compressor::with_capacity(255);
408        w.clone().chain(ecr.clone()).unwrap().compress(&mut buf).unwrap();
409        assert_eq!(buf.freeze().as_ref(),
410                   b"\x03www\x07example\x03com\x00");
411
412        let mut buf = Compressor::with_capacity(255);
413        w.clone().chain(ec.clone()).unwrap().chain(Dname::root()).unwrap()
414         .compress(&mut buf).unwrap();
415        assert_eq!(buf.freeze().as_ref(),
416                   b"\x03www\x07example\x03com\x00");
417
418        let mut buf = Compressor::with_capacity(255);
419        UncertainDname::from(w.clone()).chain(ecr.clone()).unwrap()
420            .compress(&mut buf).unwrap();
421        assert_eq!(buf.freeze().as_ref(),
422                   b"\x03www\x07example\x03com\x00");
423
424        let mut buf = Compressor::with_capacity(255);
425        UncertainDname::from(ecr.clone()).chain(fbr.clone()).unwrap()
426            .compress(&mut buf).unwrap();
427        assert_eq!(buf.freeze().as_ref(),
428                   b"\x07example\x03com\x00");
429    }
430}