1use super::FrameControl;
4use super::FrameVersion;
5use super::{Error, Result};
6
7#[derive(Debug, PartialEq, Eq, Clone, Copy)]
9#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
10pub enum Address {
11 Absent,
13 Short([u8; 2]),
15 Extended([u8; 8]),
17}
18
19impl Address {
20 pub const BROADCAST: Address = Address::Short([0xff; 2]);
22
23 pub fn is_unicast(&self) -> bool {
25 !self.is_broadcast()
26 }
27
28 pub fn is_broadcast(&self) -> bool {
30 *self == Self::BROADCAST
31 }
32
33 pub fn from(a: &[u8]) -> Self {
35 if a.is_empty() {
36 Address::Absent
37 } else if a.len() == 2 {
38 let mut b = [0u8; 2];
39 b.copy_from_slice(a);
40 Address::Short(b)
41 } else if a.len() == 8 {
42 let mut b = [0u8; 8];
43 b.copy_from_slice(a);
44 Address::Extended(b)
45 } else {
46 unreachable!()
47 }
48 }
49
50 pub const fn as_bytes(&self) -> &[u8] {
52 match self {
53 Address::Absent => &[],
54 Address::Short(value) => value,
55 Address::Extended(value) => value,
56 }
57 }
58
59 pub fn to_short(&self) -> Option<Self> {
61 match self {
62 short @ Address::Short(_) => Some(*short),
63 Address::Extended(value) => {
64 let mut raw = [0u8; 2];
65 raw.copy_from_slice(&value[..2]);
66 Some(Address::Short(raw))
67 }
68 _ => None,
69 }
70 }
71
72 const fn short_from_bytes(a: [u8; 2]) -> Self {
74 Self::Short(a)
75 }
76
77 const fn extended_from_bytes(a: [u8; 8]) -> Self {
79 Self::Extended(a)
80 }
81
82 #[allow(clippy::len_without_is_empty)]
84 pub fn len(&self) -> usize {
85 match self {
86 Address::Absent => 0,
87 Address::Short(_) => 2,
88 Address::Extended(_) => 8,
89 }
90 }
91
92 pub fn is_absent(&self) -> bool {
94 matches!(self, Address::Absent)
95 }
96
97 pub fn is_short(&self) -> bool {
99 matches!(self, Address::Short(_))
100 }
101
102 pub fn is_extended(&self) -> bool {
104 matches!(self, Address::Extended(_))
105 }
106
107 #[cfg(any(feature = "std", test))]
109 pub fn parse(s: &str) -> Result<Self> {
110 if s.is_empty() {
111 return Ok(Address::Absent);
112 }
113
114 let parts: Vec<&str> = s.split(':').collect();
115 match parts.len() {
116 2 => {
117 let mut bytes = [0u8; 2];
118 for (i, part) in parts.iter().enumerate() {
119 bytes[i] = u8::from_str_radix(part, 16).unwrap();
120 }
121 Ok(Address::Short(bytes))
122 }
123 8 => {
124 let mut bytes = [0u8; 8];
125 for (i, part) in parts.iter().enumerate() {
126 bytes[i] = u8::from_str_radix(part, 16).unwrap();
127 }
128 Ok(Address::Extended(bytes))
129 }
130 _ => Err(Error),
131 }
132 }
133}
134
135impl From<Address> for AddressingMode {
136 fn from(value: Address) -> Self {
137 match value {
138 Address::Absent => AddressingMode::Absent,
139 Address::Short(_) => AddressingMode::Short,
140 Address::Extended(_) => AddressingMode::Extended,
141 }
142 }
143}
144
145impl core::fmt::Display for Address {
146 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
147 match self {
148 Address::Absent => write!(f, "absent"),
149 Address::Short(value) => write!(f, "{:02x}:{:02x}", value[0], value[1]),
150 Address::Extended(value) => write!(
151 f,
152 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
153 value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7]
154 ),
155 }
156 }
157}
158
159#[derive(Debug, Eq, PartialEq, Clone, Copy)]
161#[cfg_attr(feature = "fuzz", derive(arbitrary::Arbitrary))]
162pub enum AddressingMode {
163 Absent = 0b00,
165 Short = 0b10,
167 Extended = 0b11,
169 Unknown,
171}
172
173impl AddressingMode {
174 pub fn size(&self) -> usize {
176 match self {
177 Self::Absent => 0,
178 Self::Short => 2,
179 Self::Extended => 8,
180 Self::Unknown => 0,
181 }
182 }
183}
184
185impl From<u8> for AddressingMode {
186 fn from(value: u8) -> Self {
187 match value {
188 0b00 => Self::Absent,
189 0b10 => Self::Short,
190 0b11 => Self::Extended,
191 _ => Self::Unknown,
192 }
193 }
194}
195
196pub struct AddressingFields<T: AsRef<[u8]>, FC: AsRef<[u8]>> {
198 buffer: T,
199 fc: FrameControl<FC>,
200}
201
202impl<T: AsRef<[u8]>, FC: AsRef<[u8]>> AddressingFields<T, FC> {
203 pub fn new(buffer: T, fc: FrameControl<FC>) -> Result<Self> {
211 let af = Self::new_unchecked(buffer, fc);
212
213 if !af.check_len() {
214 return Err(Error);
215 }
216
217 Ok(af)
218 }
219
220 fn check_len(&self) -> bool {
222 let Some((dst_pan_id_present, dst_addr_mode, src_pan_id_present, src_addr_mode)) =
223 Self::address_present_flags(
224 self.fc.frame_version(),
225 self.fc.dst_addressing_mode(),
226 self.fc.src_addressing_mode(),
227 self.fc.pan_id_compression(),
228 )
229 else {
230 return false;
231 };
232
233 let expected_len = (if dst_pan_id_present { 2 } else { 0 })
234 + dst_addr_mode.size()
235 + (if src_pan_id_present { 2 } else { 0 })
236 + src_addr_mode.size();
237
238 self.buffer.as_ref().len() >= expected_len
239 }
240
241 pub fn new_unchecked(buffer: T, fc: FrameControl<FC>) -> Self {
244 Self { buffer, fc }
245 }
246
247 #[allow(clippy::len_without_is_empty)]
249 pub fn len(&self) -> usize {
250 (match self.dst_pan_id() {
251 Some(_) => 2,
252 None => 0,
253 }) + match self.fc.dst_addressing_mode() {
254 AddressingMode::Absent => 0,
255 AddressingMode::Short => 2,
256 AddressingMode::Extended => 8,
257 _ => unreachable!(),
258 } + match self.src_pan_id() {
259 Some(_) => 2,
260 None => 0,
261 } + match self.fc.src_addressing_mode() {
262 AddressingMode::Absent => 0,
263 AddressingMode::Short => 2,
264 AddressingMode::Extended => 8,
265 _ => unreachable!(),
266 }
267 }
268
269 fn address_present_flags(
270 frame_version: FrameVersion,
271 dst_addr_mode: AddressingMode,
272 src_addr_mode: AddressingMode,
273 pan_id_compression: bool,
274 ) -> Option<(bool, AddressingMode, bool, AddressingMode)> {
275 use AddressingMode::*;
276 match frame_version {
277 FrameVersion::Ieee802154_2003 | FrameVersion::Ieee802154_2006 => {
278 match (dst_addr_mode, src_addr_mode, pan_id_compression) {
279 (dst @ (Short | Extended), src @ (Short | Extended), false) => {
285 Some((true, dst, true, src))
286 }
287 (dst @ (Short | Extended), src @ (Short | Extended), true) => {
290 Some((true, dst, false, src))
291 }
292
293 (Absent, src @ (Short | Extended), false) => Some((false, Absent, true, src)),
297 (dst @ (Short | Extended), Absent, false) => Some((true, dst, false, Absent)),
298
299 _ => None,
301 }
302 }
303 FrameVersion::Ieee802154_2020 => {
304 Some(match (dst_addr_mode, src_addr_mode, pan_id_compression) {
305 (Absent, Absent, false) => (false, Absent, false, Absent),
306 (Absent, Absent, true) => (true, Absent, false, Absent),
307 (dst, Absent, false) if !matches!(dst, Absent) => (true, dst, false, Absent),
308 (dst, Absent, true) if !matches!(dst, Absent) => (false, dst, false, Absent),
309 (Absent, src, false) if !matches!(src, Absent) => (false, Absent, true, src),
310 (Absent, src, true) if !matches!(src, Absent) => (false, Absent, false, src),
311 (Extended, Extended, false) => (true, Extended, false, Extended),
312 (Extended, Extended, true) => (false, Extended, false, Extended),
313 (Short, Short, false) => (true, Short, true, Short),
314 (Short, Extended, false) => (true, Short, true, Extended),
315 (Extended, Short, false) => (true, Extended, true, Short),
316 (Short, Extended, true) => (true, Short, false, Extended),
317 (Extended, Short, true) => (true, Extended, false, Short),
318 (Short, Short, true) => (true, Short, false, Short),
319 _ => return None,
320 })
321 }
322 _ => None,
323 }
324 }
325
326 pub fn dst_address(&self) -> Option<Address> {
328 if let Some((dst_pan_id, dst_addr, _, _)) = Self::address_present_flags(
329 self.fc.frame_version(),
330 self.fc.dst_addressing_mode(),
331 self.fc.src_addressing_mode(),
332 self.fc.pan_id_compression(),
333 ) {
334 let offset = if dst_pan_id { 2 } else { 0 };
335
336 match dst_addr {
337 AddressingMode::Absent => Some(Address::Absent),
338 AddressingMode::Short => {
339 let mut raw = [0u8; 2];
340 raw.clone_from_slice(&self.buffer.as_ref()[offset..offset + 2]);
341 raw.reverse();
342 Some(Address::short_from_bytes(raw))
343 }
344 AddressingMode::Extended => {
345 let mut raw = [0u8; 8];
346 raw.clone_from_slice(&self.buffer.as_ref()[offset..offset + 8]);
347 raw.reverse();
348 Some(Address::extended_from_bytes(raw))
349 }
350 AddressingMode::Unknown => None,
351 }
352 } else {
353 None
354 }
355 }
356
357 pub fn src_address(&self) -> Option<Address> {
359 if let Some((dst_pan_id, dst_addr, src_pan_id, src_addr)) = Self::address_present_flags(
360 self.fc.frame_version(),
361 self.fc.dst_addressing_mode(),
362 self.fc.src_addressing_mode(),
363 self.fc.pan_id_compression(),
364 ) {
365 let mut offset = if dst_pan_id { 2 } else { 0 };
366 offset += dst_addr.size();
367 offset += if src_pan_id { 2 } else { 0 };
368
369 match src_addr {
370 AddressingMode::Absent => Some(Address::Absent),
371 AddressingMode::Short => {
372 let mut raw = [0u8; 2];
373 raw.clone_from_slice(&self.buffer.as_ref()[offset..offset + 2]);
374 raw.reverse();
375 Some(Address::short_from_bytes(raw))
376 }
377 AddressingMode::Extended => {
378 let mut raw = [0u8; 8];
379 raw.clone_from_slice(&self.buffer.as_ref()[offset..offset + 8]);
380 raw.reverse();
381 Some(Address::extended_from_bytes(raw))
382 }
383 AddressingMode::Unknown => None,
384 }
385 } else {
386 None
387 }
388 }
389
390 pub fn dst_pan_id(&self) -> Option<u16> {
392 if let Some((true, _, _, _)) = Self::address_present_flags(
393 self.fc.frame_version(),
394 self.fc.dst_addressing_mode(),
395 self.fc.src_addressing_mode(),
396 self.fc.pan_id_compression(),
397 ) {
398 let b = &self.buffer.as_ref()[..2];
399 Some(u16::from_le_bytes([b[0], b[1]]))
400 } else {
401 None
402 }
403 }
404
405 pub fn src_pan_id(&self) -> Option<u16> {
407 if let Some((dst_pan_id, dst_addr, true, _)) = Self::address_present_flags(
408 self.fc.frame_version(),
409 self.fc.dst_addressing_mode(),
410 self.fc.src_addressing_mode(),
411 self.fc.pan_id_compression(),
412 ) {
413 let mut offset = if dst_pan_id { 2 } else { 0 };
414 offset += dst_addr.size();
415
416 let b = &self.buffer.as_ref()[offset..][..2];
417 Some(u16::from_le_bytes([b[0], b[1]]))
418 } else {
419 None
420 }
421 }
422}
423
424impl<T: AsRef<[u8]>, FC: AsRef<[u8]>> core::fmt::Display for AddressingFields<T, FC> {
425 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
426 writeln!(f, "Addressing Fields")?;
427
428 if let Some(id) = self.dst_pan_id() {
429 writeln!(f, " dst pan id: {:0x}", id)?;
430 }
431
432 if let Some(addr) = self.dst_address() {
433 writeln!(f, " dst address: {}", addr)?;
434 }
435
436 if let Some(id) = self.src_pan_id() {
437 writeln!(f, " src pan id: {:0x}", id)?;
438 }
439
440 if let Some(addr) = self.src_address() {
441 writeln!(f, " src address: {}", addr)?;
442 }
443
444 Ok(())
445 }
446}
447
448impl<T: AsRef<[u8]> + AsMut<[u8]>, FC: AsRef<[u8]>> AddressingFields<T, FC> {
449 pub fn write_fields(&mut self, fields: &super::repr::AddressingFieldsRepr) {
451 let mut offset = 0;
452
453 if let Some(id) = fields.dst_pan_id {
454 let b = &mut self.buffer.as_mut()[offset..][..2];
455 b.copy_from_slice(&id.to_le_bytes());
456 offset += 2;
457 }
458
459 if let Some(addr) = fields.dst_address {
460 let b = &mut self.buffer.as_mut()[offset..][..addr.len()];
461 match addr {
462 Address::Absent => {}
463 Address::Short(value) => {
464 let mut addr = value;
465 addr.reverse();
466 b.copy_from_slice(&addr);
467 }
468 Address::Extended(value) => {
469 let mut addr = value;
470 addr.reverse();
471 b.copy_from_slice(&addr);
472 }
473 }
474 offset += addr.len();
475 }
476
477 if let Some(id) = fields.src_pan_id {
478 let b = &mut self.buffer.as_mut()[offset..][..2];
479 b.copy_from_slice(&id.to_le_bytes());
480 offset += 2;
481 }
482
483 if let Some(addr) = fields.src_address {
484 let b = &mut self.buffer.as_mut()[offset..][..addr.len()];
485 match addr {
486 Address::Absent => {}
487 Address::Short(value) => {
488 let mut addr = value;
489 addr.reverse();
490 b.copy_from_slice(&addr);
491 }
492 Address::Extended(value) => {
493 let mut addr = value;
494 addr.reverse();
495 b.copy_from_slice(&addr);
496 }
497 }
498 }
499 }
500}
501
502#[cfg(test)]
503mod tests {
504 use super::*;
505
506 #[test]
507 fn address_type() {
508 assert!(Address::Absent.is_absent());
509 assert!(!Address::Absent.is_short());
510 assert!(!Address::Absent.is_extended());
511
512 assert!(!Address::Short([0xff, 0xff]).is_absent());
513 assert!(Address::Short([0xff, 0xff]).is_short());
514 assert!(!Address::Short([0xff, 0xff]).is_extended());
515
516 assert!(!Address::Extended([0xff; 8]).is_absent());
517 assert!(!Address::Extended([0xff; 8]).is_short());
518 assert!(Address::Extended([0xff; 8]).is_extended());
519
520 assert_eq!(Address::Absent.len(), 0);
521 assert_eq!(Address::Short([0xff, 0xff]).len(), 2);
522 assert_eq!(Address::Extended([0xff; 8]).len(), 8);
523 }
524
525 #[test]
526 fn addressing_mode() {
527 assert_eq!(AddressingMode::from(0b00), AddressingMode::Absent);
528 assert_eq!(AddressingMode::from(0b10), AddressingMode::Short);
529 assert_eq!(AddressingMode::from(0b11), AddressingMode::Extended);
530 assert_eq!(AddressingMode::from(0b01), AddressingMode::Unknown);
531
532 assert_eq!(AddressingMode::Unknown.size(), 0);
533 assert_eq!(AddressingMode::Absent.size(), 0);
534 assert_eq!(AddressingMode::Short.size(), 2);
535 assert_eq!(AddressingMode::Extended.size(), 8);
536 }
537
538 #[test]
539 fn is_broadcast() {
540 assert!(Address::BROADCAST.is_broadcast());
541 assert!(Address::Short([0xff, 0xff]).is_broadcast());
542 assert!(!Address::Short([0xff, 0xfe]).is_broadcast());
543
544 assert!(!Address::BROADCAST.is_unicast());
545 assert!(!Address::Short([0xff, 0xff]).is_unicast());
546 assert!(Address::Short([0xff, 0xfe]).is_unicast());
547 }
548
549 #[test]
550 fn as_bytes() {
551 assert_eq!(Address::BROADCAST.as_bytes(), &[0xff, 0xff]);
552 assert_eq!(Address::Short([0xff, 0xff]).as_bytes(), &[0xff, 0xff]);
553 assert_eq!(Address::Short([0xff, 0xfe]).as_bytes(), &[0xff, 0xfe]);
554 assert_eq!(Address::Extended([0xff; 8]).as_bytes(), &[0xff; 8]);
555 assert_eq!(Address::Extended([0x01; 8]).as_bytes(), &[0x01; 8]);
556 assert_eq!(Address::Absent.as_bytes(), &[]);
557 }
558
559 #[test]
560 fn from_bytes() {
561 assert_eq!(Address::from(&[0xff, 0xff]), Address::Short([0xff, 0xff]));
562 assert_eq!(Address::from(&[0xff, 0xfe]), Address::Short([0xff, 0xfe]));
563 assert_eq!(Address::from(&[0xff; 8]), Address::Extended([0xff; 8]));
564 assert_eq!(Address::from(&[0x01; 8]), Address::Extended([0x01; 8]));
565 assert_eq!(Address::from(&[]), Address::Absent);
566 }
567
568 #[test]
569 #[should_panic]
570 fn from_bytes_panic() {
571 Address::from(&[0xff, 0xff, 0xff]);
572 }
573
574 #[test]
575 fn address_present_flags() {
576 use AddressingMode::*;
577 use FrameVersion::*;
578
579 macro_rules! check {
580 (($version:ident, $dst:ident, $src:ident, $compression:literal) -> $expected:expr) => {
581 assert_eq!(
582 AddressingFields::<&[u8], &[u8]>::address_present_flags(
583 $version,
584 $dst,
585 $src,
586 $compression
587 ),
588 $expected
589 );
590 };
591 }
592
593 check!((Ieee802154_2003, Short, Short, false) -> Some((true, Short, true, Short)));
594 check!((Ieee802154_2003, Short, Short, true) -> Some((true, Short, false, Short)));
595 check!((Ieee802154_2003, Extended, Extended, false) -> Some((true, Extended, true, Extended)));
596 check!((Ieee802154_2003, Extended, Extended, true) -> Some((true, Extended, false, Extended)));
597 check!((Ieee802154_2003, Short, Extended, false) -> Some((true, Short, true, Extended)));
598 check!((Ieee802154_2003, Short, Extended, true) -> Some((true, Short, false, Extended)));
599 check!((Ieee802154_2003, Extended, Short, false) -> Some((true, Extended, true, Short)));
600 check!((Ieee802154_2003, Extended, Short, true) -> Some((true, Extended, false, Short)));
601 check!((Ieee802154_2003, Absent, Short, false) -> Some((false, Absent, true, Short)));
602 check!((Ieee802154_2003, Absent, Extended, false) -> Some((false, Absent, true, Extended)));
603 check!((Ieee802154_2003, Short, Absent, false) -> Some((true, Short, false, Absent)));
604 check!((Ieee802154_2003, Extended, Absent, false) -> Some((true, Extended, false, Absent)));
605 check!((Ieee802154_2003, Absent, Short, true) -> None);
606 check!((Ieee802154_2003, Absent, Extended, true) -> None);
607 check!((Ieee802154_2003, Short, Absent, true) -> None);
608 check!((Ieee802154_2003, Extended, Absent, true) -> None);
609 check!((Ieee802154_2003, Absent, Absent, false) -> None);
610 check!((Ieee802154_2003, Absent, Absent, true) -> None);
611
612 check!((Ieee802154_2006, Short, Short, false) -> Some((true, Short, true, Short)));
613 check!((Ieee802154_2006, Short, Short, true) -> Some((true, Short, false, Short)));
614 check!((Ieee802154_2006, Extended, Extended, false) -> Some((true, Extended, true, Extended)));
615 check!((Ieee802154_2006, Extended, Extended, true) -> Some((true, Extended, false, Extended)));
616 check!((Ieee802154_2006, Short, Extended, false) -> Some((true, Short, true, Extended)));
617 check!((Ieee802154_2006, Short, Extended, true) -> Some((true, Short, false, Extended)));
618 check!((Ieee802154_2006, Extended, Short, false) -> Some((true, Extended, true, Short)));
619 check!((Ieee802154_2006, Extended, Short, true) -> Some((true, Extended, false, Short)));
620 check!((Ieee802154_2006, Absent, Short, false) -> Some((false, Absent, true, Short)));
621 check!((Ieee802154_2006, Absent, Extended, false) -> Some((false, Absent, true, Extended)));
622 check!((Ieee802154_2006, Short, Absent, false) -> Some((true, Short, false, Absent)));
623 check!((Ieee802154_2006, Extended, Absent, false) -> Some((true, Extended, false, Absent)));
624 check!((Ieee802154_2006, Absent, Short, true) -> None);
625 check!((Ieee802154_2006, Absent, Extended, true) -> None);
626 check!((Ieee802154_2006, Short, Absent, true) -> None);
627 check!((Ieee802154_2006, Extended, Absent, true) -> None);
628 check!((Ieee802154_2006, Absent, Absent, false) -> None);
629 check!((Ieee802154_2006, Absent, Absent, true) -> None);
630
631 check!((Ieee802154_2020, Short, Short, false) -> Some((true, Short, true, Short)));
632 check!((Ieee802154_2020, Short, Short, true) -> Some((true, Short, false, Short)));
633 check!((Ieee802154_2020, Extended, Extended, false) -> Some((true, Extended, false, Extended)));
634 check!((Ieee802154_2020, Extended, Extended, true) -> Some((false, Extended, false, Extended)));
635 check!((Ieee802154_2020, Short, Extended, false) -> Some((true, Short, true, Extended)));
636 check!((Ieee802154_2020, Short, Extended, true) -> Some((true, Short, false, Extended)));
637 check!((Ieee802154_2020, Extended, Short, false) -> Some((true, Extended, true, Short)));
638 check!((Ieee802154_2020, Extended, Short, true) -> Some((true, Extended, false, Short)));
639 check!((Ieee802154_2020, Absent, Short, false) -> Some((false, Absent, true, Short)));
640 check!((Ieee802154_2020, Absent, Extended, false) -> Some((false, Absent, true, Extended)));
641 check!((Ieee802154_2020, Short, Absent, false) -> Some((true, Short, false, Absent)));
642 check!((Ieee802154_2020, Extended, Absent, false) -> Some((true, Extended, false, Absent)));
643 check!((Ieee802154_2020, Absent, Short, true) -> Some((false, Absent, false, Short)));
644 check!((Ieee802154_2020, Absent, Extended, true) -> Some((false, Absent, false, Extended)));
645 check!((Ieee802154_2020, Short, Absent, true) -> Some((false, Short, false, Absent)));
646 check!((Ieee802154_2020, Extended, Absent, true) -> Some((false, Extended, false, Absent)));
647 check!((Ieee802154_2020, Absent, Absent, false) -> Some((false, Absent, false, Absent)));
648 check!((Ieee802154_2020, Absent, Absent, true) -> Some((true, Absent, false, Absent)));
649 }
650
651 #[test]
652 fn parse() {
653 let mut addresses = vec![
654 ("", Address::Absent),
655 ("ff:ff", Address::Short([0xff, 0xff])),
656 ("ff:fe", Address::Short([0xff, 0xfe])),
657 ("ff:ff:ff:ff:ff:ff:ff:ff", Address::Extended([0xff; 8])),
658 ("01:01:01:01:01:01:01:01", Address::Extended([0x01; 8])),
659 ("00:00:00:00:00:00:00:00", Address::Extended([0x00; 8])),
660 (
661 "00:00:00:00:00:00:00:01",
662 Address::Extended([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01]),
663 ),
664 ];
665
666 for (s, expected) in addresses.drain(..) {
667 assert_eq!(Address::parse(s).unwrap(), expected);
668 }
669 }
670}