Skip to main content

en_300_468_reader/
lib.rs

1//! Types for reading _Service Information_ from a DVB MPEG Transport Stream, formatted according
2//! to  [ETSI standard EN 300 486](http://www.etsi.org/deliver/etsi_en/300400_300499/300468/01.15.01_60/en_300468v011501p.pdf).
3#![forbid(unsafe_code)]
4#![deny(rust_2018_idioms, future_incompatible)]
5
6pub mod sdt;
7
8use mpeg2ts_reader::descriptor::UnknownDescriptor;
9
10use crate::sdt::ServiceDescriptor;
11use encoding::Encoding;
12use std::borrow::Cow;
13use std::fmt;
14
15mpeg2ts_reader::descriptor_enum! {
16    /// All descriptors supported by this crate.
17    ///
18    /// Future releases of this crate should replace most `UnknownDescriptor` with
19    /// descriptor-specific implementations.
20    #[derive(Debug)]
21    En300_468Descriptors {
22        Reserved 0|1|36..=63 => UnknownDescriptor,
23        VideoStream 2 => UnknownDescriptor,
24        AudioStream 3 => UnknownDescriptor,
25        Hierarchy 4 => UnknownDescriptor,
26        Registration 5 => UnknownDescriptor,
27        DataStreamAlignment 6 => UnknownDescriptor,
28        TargetBackgroundGrid 7 => UnknownDescriptor,
29        VideoWindow 8 => UnknownDescriptor,
30        CA 9 => UnknownDescriptor,
31        ISO639Language 10 => UnknownDescriptor,
32        SystemClock 11 => UnknownDescriptor,
33        MultiplexBufferUtilization 12 => UnknownDescriptor,
34        Copyright 13 => UnknownDescriptor,
35        MaximumBitrate 14 => UnknownDescriptor,
36        PrivateDataIndicator 15 => UnknownDescriptor,
37        SmoothingBuffer 16 => UnknownDescriptor,
38        STD 17 => UnknownDescriptor,
39        IBP 18 => UnknownDescriptor,
40        /// ISO IEC 13818-6
41        IsoIec13818dash6 19..=26 => UnknownDescriptor,
42        MPEG4Video 27 => UnknownDescriptor,
43        MPEG4Audio 28 => UnknownDescriptor,
44        IOD 29 => UnknownDescriptor,
45        SL 30 => UnknownDescriptor,
46        FMC 31 => UnknownDescriptor,
47        ExternalESID 32 => UnknownDescriptor,
48        MuxCode 33 => UnknownDescriptor,
49        FmxBufferSize 34 => UnknownDescriptor,
50        MultiplexBuffer 35 => UnknownDescriptor,
51        UserPrivate 69..=70|103..=254 => UnknownDescriptor,
52
53        // EN 300 480 specofic descriptors,
54        NetworkName 0x40 => UnknownDescriptor,
55        ServiceList 0x41 => UnknownDescriptor,
56        Stuffing 0x42 => UnknownDescriptor,
57        SatelliteDeliverySystem 0x43 => UnknownDescriptor,
58        CableDeliverySystem 0x44 => UnknownDescriptor,
59        BouquetName 0x47 => UnknownDescriptor,
60
61        Service ServiceDescriptor::TAG => ServiceDescriptor,
62
63        CountryAvailability 0x49 => UnknownDescriptor,
64        Linkage 0x4A => UnknownDescriptor,
65        NvodReference 0x4B => UnknownDescriptor,
66        TimeShiftedService 0x4C => UnknownDescriptor,
67        ShortEvent 0x4D => UnknownDescriptor,
68        ExtendedEvent 0x4E => UnknownDescriptor,
69        TimeShiftedEvent 0x4F => UnknownDescriptor,
70        Component 0x50 => UnknownDescriptor,
71        Mosaic 0x51 => UnknownDescriptor,
72        StreamIdentifier 0x52 => UnknownDescriptor,
73        CaIdentifier 0x53 => UnknownDescriptor,
74        Content 0x54 => UnknownDescriptor,
75        ParentalRating 0x55 => UnknownDescriptor,
76        Teletext 0x56 => UnknownDescriptor,
77        Telephone 0x57 => UnknownDescriptor,
78        LocalTimeOffset 0x58 => UnknownDescriptor,
79        Subtitling 0x59 => UnknownDescriptor,
80        TerrestrialDeliverySystem 0x5A => UnknownDescriptor,
81        MultilingualNetworkName 0x5B => UnknownDescriptor,
82        MultilingualBouquetName 0x5C => UnknownDescriptor,
83        MultilingualServiceName 0x5D => UnknownDescriptor,
84        MultilingualComponent 0x5E => UnknownDescriptor,
85        PrivateDataSpecifier 0x5F => UnknownDescriptor,
86        ServiceMove 0x60 => UnknownDescriptor,
87        ShortSmoothingBuffer 0x61 => UnknownDescriptor,
88        FrequencyList 0x62 => UnknownDescriptor,
89        PartialTransportStream 0x63 => UnknownDescriptor,
90        DataBroadcast 0x64 => UnknownDescriptor,
91        CaSystem 0x65 => UnknownDescriptor,
92        DataBroadcastId 0x66 => UnknownDescriptor,
93        Forbidden 0xFF => UnknownDescriptor,
94    }
95}
96
97/// Text encodings as defined by _ETSI EN 300 468_, used by the [`Text type`](struct.Text.html).
98#[derive(Debug)]
99pub enum TextEncoding {
100    Reserved1(u8),
101    Reserved2(u8, u8),
102    /// ISO 8859-1
103    Iso88591,
104    /// ISO 8859-2
105    Iso88592,
106    /// ISO 8859-3
107    Iso88593,
108    /// ISO 8859-4
109    Iso88594,
110    /// ISO 8859-5
111    Iso88595,
112    /// ISO 8859-6
113    Iso88596,
114    /// ISO 8859-7
115    Iso88597,
116    /// ISO 8859-8
117    Iso88598,
118    /// ISO 8859-9
119    Iso88599,
120    /// ISO 8859-10
121    Iso885910,
122    /// ISO 8859-11
123    Iso885911,
124    /// ISO 8859-13
125    Iso885913,
126    /// ISO 8859-14
127    Iso885914,
128    /// ISO 8859-15
129    Iso885915,
130    /// ISO 10646
131    Iso10646,
132    /// KSX1001-2004
133    KSX1001_2004,
134    /// GB-2312-1980
135    GB2312_1980,
136    /// Big5 subset of ISO/IEC 10646
137    Big5,
138    /// UTF-8,
139    UTF8,
140}
141
142/// There are several pieces of metadata in the spec that may apply to the 'actual' transport
143/// stream (i.e. the one containing the metadata) or some 'other' transport stream.  This wrapper
144/// allows these cases to be discriminated.
145///
146/// The `Other` variant allows metadata to be announced for services that are actually broadcast
147/// in a different multiplex (on a different frequency), for example.
148pub enum ActualOther<T> {
149    /// The wrapped information pertains to the current transport stream / network.
150    Actual(T),
151    /// The wrapped information pertains to some other transport stream / network.
152    Other(T),
153}
154impl<T> ActualOther<T> {
155    pub fn actual(&self) -> Option<&T> {
156        match self {
157            ActualOther::Actual(ref v) => Some(v),
158            ActualOther::Other(_) => None,
159        }
160    }
161    pub fn other(&self) -> Option<&T> {
162        match self {
163            ActualOther::Actual(_) => None,
164            ActualOther::Other(ref v) => Some(v),
165        }
166    }
167}
168
169/// A problem encountered by [`Text::to_string()`](struct.Text.html#method.to_string).
170#[derive(Debug)]
171pub enum TextError {
172    NotEnoughData { expected: usize, available: usize },
173    DecodeFailure(Cow<'static, str>),
174    UnsupportedEncoding(TextEncoding),
175}
176
177/// A wrapper around bytes representing text having embedded encoding information, with
178/// functionality for trying to decode this a Rust `String`.
179pub struct Text<'buf> {
180    data: &'buf [u8],
181}
182impl<'buf> Text<'buf> {
183    pub fn new(data: &'buf [u8]) -> Result<Text<'buf>, TextError> {
184        if data.is_empty() {
185            Err(TextError::NotEnoughData {
186                expected: 1,
187                available: 0,
188            })
189        } else {
190            Ok(Text { data })
191        }
192    }
193    pub fn encoding(&self) -> TextEncoding {
194        let id = self.data[0];
195        match id {
196            0x20..=0xff => TextEncoding::Iso88591,
197            0x01 => TextEncoding::Iso88595,
198            0x02 => TextEncoding::Iso88596,
199            0x03 => TextEncoding::Iso88597,
200            0x04 => TextEncoding::Iso88598,
201            0x05 => TextEncoding::Iso88599,
202            0x06 => TextEncoding::Iso885910,
203            0x07 => TextEncoding::Iso885911,
204            0x08 => TextEncoding::Reserved1(id),
205            0x09 => TextEncoding::Iso885913,
206            0x0a => TextEncoding::Iso885914,
207            0x0b => TextEncoding::Iso885915,
208            0x0c..=0x0f => TextEncoding::Reserved1(id),
209            0x10 => {
210                let ids = (self.data[1], self.data[2]);
211                match ids {
212                    (0x00, 0x00) => TextEncoding::Reserved2(ids.0, ids.1),
213                    (0x00, 0x01) => TextEncoding::Iso88591,
214                    (0x00, 0x02) => TextEncoding::Iso88592,
215                    (0x00, 0x03) => TextEncoding::Iso88593,
216                    (0x00, 0x04) => TextEncoding::Iso88594,
217                    (0x00, 0x05) => TextEncoding::Iso88595,
218                    (0x00, 0x06) => TextEncoding::Iso88596,
219                    (0x00, 0x07) => TextEncoding::Iso88597,
220                    (0x00, 0x08) => TextEncoding::Iso88598,
221                    (0x00, 0x09) => TextEncoding::Iso88599,
222                    (0x00, 0x0a) => TextEncoding::Iso885910,
223                    (0x00, 0x0b) => TextEncoding::Iso885911,
224                    (0x00, 0x0c) => TextEncoding::Reserved2(ids.0, ids.1),
225                    (0x00, 0x0d) => TextEncoding::Iso885913,
226                    (0x00, 0x0e) => TextEncoding::Iso885914,
227                    (0x00, 0x0f) => TextEncoding::Iso885915,
228                    _ => TextEncoding::Reserved2(ids.0, ids.1),
229                }
230            }
231            0x11 => TextEncoding::Iso10646,
232            0x12 => TextEncoding::KSX1001_2004,
233            0x13 => TextEncoding::GB2312_1980,
234            0x14 => TextEncoding::Big5,
235            0x15 => TextEncoding::UTF8,
236            0x16..=0x1E => TextEncoding::Reserved1(id),
237            0x1F => unimplemented!("encoding_type_id"),
238            _ => unreachable!(),
239        }
240    }
241    fn buffer(&self) -> Result<&'buf [u8], TextError> {
242        Ok(&self.data[self.enc_prefix_len()?..])
243    }
244    fn enc_prefix_len(&self) -> Result<usize, TextError> {
245        match self.data[0] {
246            0x01..=0x0f | 0x11..=0x1e => Ok(1),
247            0x1f => Ok(2), // encoding_type_id in second byte
248            0x10 => {
249                if self.data.len() < 3 {
250                    Err(TextError::NotEnoughData {
251                        expected: 3,
252                        available: self.data.len(),
253                    })
254                } else {
255                    Ok(3)
256                }
257            }
258            0x20..=0xff => Ok(0),
259            _ => unreachable!(),
260        }
261    }
262
263    pub fn to_string(&self, trap: encoding::types::DecoderTrap) -> Result<String, TextError> {
264        let enc = self.encoding();
265        match enc {
266            TextEncoding::Iso88591 => encoding::all::ISO_8859_1
267                .decode(self.buffer()?, trap)
268                .map_err(TextError::DecodeFailure),
269            TextEncoding::Iso88592 => encoding::all::ISO_8859_2
270                .decode(self.buffer()?, trap)
271                .map_err(TextError::DecodeFailure),
272            TextEncoding::Iso88593 => encoding::all::ISO_8859_3
273                .decode(self.buffer()?, trap)
274                .map_err(TextError::DecodeFailure),
275            TextEncoding::Iso88594 => encoding::all::ISO_8859_4
276                .decode(self.buffer()?, trap)
277                .map_err(TextError::DecodeFailure),
278            TextEncoding::Iso88595 => encoding::all::ISO_8859_5
279                .decode(self.buffer()?, trap)
280                .map_err(TextError::DecodeFailure),
281            TextEncoding::Iso88596 => encoding::all::ISO_8859_6
282                .decode(self.buffer()?, trap)
283                .map_err(TextError::DecodeFailure),
284            TextEncoding::Iso88597 => encoding::all::ISO_8859_7
285                .decode(self.buffer()?, trap)
286                .map_err(TextError::DecodeFailure),
287            TextEncoding::Iso88598 => encoding::all::ISO_8859_8
288                .decode(self.buffer()?, trap)
289                .map_err(TextError::DecodeFailure),
290            TextEncoding::Iso88599 => Err(TextError::UnsupportedEncoding(enc)),
291            TextEncoding::Iso885910 => encoding::all::ISO_8859_10
292                .decode(self.buffer()?, trap)
293                .map_err(TextError::DecodeFailure),
294            TextEncoding::Iso885911 => Err(TextError::UnsupportedEncoding(enc)),
295            TextEncoding::Iso885913 => encoding::all::ISO_8859_13
296                .decode(self.buffer()?, trap)
297                .map_err(TextError::DecodeFailure),
298            TextEncoding::Iso885914 => encoding::all::ISO_8859_14
299                .decode(self.buffer()?, trap)
300                .map_err(TextError::DecodeFailure),
301            TextEncoding::Iso885915 => encoding::all::ISO_8859_15
302                .decode(self.buffer()?, trap)
303                .map_err(TextError::DecodeFailure),
304            TextEncoding::Reserved1(..) => Err(TextError::UnsupportedEncoding(enc)),
305            TextEncoding::Reserved2(..) => Err(TextError::UnsupportedEncoding(enc)),
306            TextEncoding::Iso10646 => Err(TextError::UnsupportedEncoding(enc)),
307            TextEncoding::KSX1001_2004 => Err(TextError::UnsupportedEncoding(enc)),
308            TextEncoding::GB2312_1980 => Err(TextError::UnsupportedEncoding(enc)),
309            TextEncoding::Big5 => encoding::all::BIG5_2003
310                .decode(self.buffer()?, trap)
311                .map_err(TextError::DecodeFailure),
312            TextEncoding::UTF8 => encoding::all::UTF_8
313                .decode(self.buffer()?, trap)
314                .map_err(TextError::DecodeFailure),
315        }
316    }
317}
318impl<'buf> fmt::Debug for Text<'buf> {
319    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
320        fmt::Debug::fmt(&self.to_string(encoding::DecoderTrap::Replace), f)
321    }
322}