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        let (hdr, _) =
31            sel.split_first_chunk::<SERVICE_RELOCATED_LEN>()
32                .ok_or(Error::BufferTooShort {
33                    need: SERVICE_RELOCATED_LEN,
34                    have: sel.len(),
35                    what: "service_relocated body",
36                })?;
37        Ok(ServiceRelocated {
38            old_original_network_id: u16::from_be_bytes([hdr[0], hdr[1]]),
39            old_transport_stream_id: u16::from_be_bytes([hdr[2], hdr[3]]),
40            old_service_id: u16::from_be_bytes([hdr[4], hdr[5]]),
41        })
42    }
43}
44
45impl Serialize for ServiceRelocated {
46    type Error = crate::error::Error;
47    fn serialized_len(&self) -> usize {
48        SERVICE_RELOCATED_LEN
49    }
50    fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
51        let len = self.serialized_len();
52        if buf.len() < len {
53            return Err(Error::OutputBufferTooSmall {
54                need: len,
55                have: buf.len(),
56            });
57        }
58        buf[0..2].copy_from_slice(&self.old_original_network_id.to_be_bytes());
59        buf[2..4].copy_from_slice(&self.old_transport_stream_id.to_be_bytes());
60        buf[4..6].copy_from_slice(&self.old_service_id.to_be_bytes());
61        Ok(len)
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68    use crate::descriptors::extension::test_support::*;
69    use crate::descriptors::extension::{ExtensionBody, ExtensionDescriptor, ExtensionTag};
70
71    #[test]
72    fn parse_service_relocated() {
73        let sel = [0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC];
74        let bytes = wrap(0x0B, &sel);
75        let d = ExtensionDescriptor::parse(&bytes).unwrap();
76        assert_eq!(d.kind(), Some(ExtensionTag::ServiceRelocated));
77        match &d.body {
78            ExtensionBody::ServiceRelocated(b) => {
79                assert_eq!(b.old_original_network_id, 0x1234);
80                assert_eq!(b.old_transport_stream_id, 0x5678);
81                assert_eq!(b.old_service_id, 0x9ABC);
82            }
83            other => panic!("expected ServiceRelocated, got {other:?}"),
84        }
85        round_trip(&d);
86    }
87}