Skip to main content

dvb_si/descriptors/extension/
service_relocated.rs

1//! Service Relocated Descriptor — ETSI EN 300 468 §6.4.10 (tag_extension 0x0B).
2use super::*;
3
4impl<'a> ExtensionBodyDef<'a> for ServiceRelocated {
5    const TAG_EXTENSION: u8 = 0x0B;
6    const NAME: &'static str = "SERVICE_RELOCATED";
7}
8/// service_relocated body (Table 152) — fully typed, fixed 6 bytes.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize))]
11pub struct ServiceRelocated {
12    /// old_original_network_id(16).
13    pub old_original_network_id: u16,
14    /// old_transport_stream_id(16).
15    pub old_transport_stream_id: u16,
16    /// old_service_id(16).
17    pub old_service_id: u16,
18}
19
20impl<'a> Parse<'a> for ServiceRelocated {
21    type Error = crate::error::Error;
22    fn parse(sel: &'a [u8]) -> Result<Self> {
23        if sel.len() < SERVICE_RELOCATED_LEN {
24            return Err(Error::BufferTooShort {
25                need: SERVICE_RELOCATED_LEN,
26                have: sel.len(),
27                what: "service_relocated body",
28            });
29        }
30        Ok(ServiceRelocated {
31            old_original_network_id: u16::from_be_bytes([sel[0], sel[1]]),
32            old_transport_stream_id: u16::from_be_bytes([sel[2], sel[3]]),
33            old_service_id: u16::from_be_bytes([sel[4], sel[5]]),
34        })
35    }
36}
37
38impl Serialize for ServiceRelocated {
39    type Error = crate::error::Error;
40    fn serialized_len(&self) -> usize {
41        SERVICE_RELOCATED_LEN
42    }
43    fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
44        let len = self.serialized_len();
45        if buf.len() < len {
46            return Err(Error::OutputBufferTooSmall {
47                need: len,
48                have: buf.len(),
49            });
50        }
51        buf[0..2].copy_from_slice(&self.old_original_network_id.to_be_bytes());
52        buf[2..4].copy_from_slice(&self.old_transport_stream_id.to_be_bytes());
53        buf[4..6].copy_from_slice(&self.old_service_id.to_be_bytes());
54        Ok(len)
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61    use crate::descriptors::extension::test_support::*;
62    use crate::descriptors::extension::{ExtensionBody, ExtensionDescriptor, ExtensionTag};
63
64    #[test]
65    fn parse_service_relocated() {
66        let sel = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC];
67        let bytes = wrap(0x0B, &sel);
68        let d = ExtensionDescriptor::parse(&bytes).unwrap();
69        assert_eq!(d.kind(), Some(ExtensionTag::ServiceRelocated));
70        match &d.body {
71            ExtensionBody::ServiceRelocated(b) => {
72                assert_eq!(b.old_original_network_id, 0x1234);
73                assert_eq!(b.old_transport_stream_id, 0x5678);
74                assert_eq!(b.old_service_id, 0x9ABC);
75            }
76            other => panic!("expected ServiceRelocated, got {other:?}"),
77        }
78        round_trip(&d);
79    }
80}