style/servo/
encoding_support.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! Parsing stylesheets from bytes (not `&str`).
6
7use crate::context::QuirksMode;
8use crate::error_reporting::ParseErrorReporter;
9use crate::media_queries::MediaList;
10use crate::shared_lock::SharedRwLock;
11use crate::stylesheets::{AllowImportRules, Origin, Stylesheet, StylesheetLoader, UrlExtraData};
12use cssparser::{stylesheet_encoding, EncodingSupport};
13use servo_arc::Arc;
14use std::borrow::Cow;
15use std::str;
16
17struct EncodingRs;
18
19impl EncodingSupport for EncodingRs {
20    type Encoding = &'static encoding_rs::Encoding;
21
22    fn utf8() -> Self::Encoding {
23        encoding_rs::UTF_8
24    }
25
26    fn is_utf16_be_or_le(encoding: &Self::Encoding) -> bool {
27        *encoding == encoding_rs::UTF_16LE || *encoding == encoding_rs::UTF_16BE
28    }
29
30    fn from_label(ascii_label: &[u8]) -> Option<Self::Encoding> {
31        encoding_rs::Encoding::for_label(ascii_label)
32    }
33}
34
35fn decode_stylesheet_bytes<'a>(
36    css: &'a [u8],
37    protocol_encoding_label: Option<&str>,
38    environment_encoding: Option<&'static encoding_rs::Encoding>,
39) -> Cow<'a, str> {
40    let fallback_encoding = stylesheet_encoding::<EncodingRs>(
41        css,
42        protocol_encoding_label.map(str::as_bytes),
43        environment_encoding,
44    );
45    let (result, _used_encoding, _) = fallback_encoding.decode(&css);
46    // FIXME record used encoding for environment encoding of @import
47    result
48}
49
50impl Stylesheet {
51    /// Parse a stylesheet from a set of bytes, potentially received over the
52    /// network.
53    ///
54    /// Takes care of decoding the network bytes and forwards the resulting
55    /// string to `Stylesheet::from_str`.
56    pub fn from_bytes(
57        bytes: &[u8],
58        url_data: UrlExtraData,
59        protocol_encoding_label: Option<&str>,
60        environment_encoding: Option<&'static encoding_rs::Encoding>,
61        origin: Origin,
62        media: MediaList,
63        shared_lock: SharedRwLock,
64        stylesheet_loader: Option<&dyn StylesheetLoader>,
65        error_reporter: Option<&dyn ParseErrorReporter>,
66        quirks_mode: QuirksMode,
67    ) -> Stylesheet {
68        let string = decode_stylesheet_bytes(bytes, protocol_encoding_label, environment_encoding);
69        Stylesheet::from_str(
70            &string,
71            url_data,
72            origin,
73            Arc::new(shared_lock.wrap(media)),
74            shared_lock,
75            stylesheet_loader,
76            error_reporter,
77            quirks_mode,
78            AllowImportRules::Yes,
79        )
80    }
81
82    /// Updates an empty stylesheet with a set of bytes that reached over the
83    /// network.
84    pub fn update_from_bytes(
85        existing: &Stylesheet,
86        bytes: &[u8],
87        protocol_encoding_label: Option<&str>,
88        environment_encoding: Option<&'static encoding_rs::Encoding>,
89        url_data: UrlExtraData,
90        stylesheet_loader: Option<&dyn StylesheetLoader>,
91        error_reporter: Option<&dyn ParseErrorReporter>,
92    ) {
93        let string = decode_stylesheet_bytes(bytes, protocol_encoding_label, environment_encoding);
94        Self::update_from_str(
95            existing,
96            &string,
97            url_data,
98            stylesheet_loader,
99            error_reporter,
100            AllowImportRules::Yes,
101        )
102    }
103}