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 
7 use crate::context::QuirksMode;
8 use crate::error_reporting::ParseErrorReporter;
9 use crate::media_queries::MediaList;
10 use crate::shared_lock::SharedRwLock;
11 use crate::stylesheets::{AllowImportRules, Origin, Stylesheet, StylesheetLoader, UrlExtraData};
12 use cssparser::{stylesheet_encoding, EncodingSupport};
13 use servo_arc::Arc;
14 use std::borrow::Cow;
15 use std::str;
16 
17 struct EncodingRs;
18 
19 impl EncodingSupport for EncodingRs {
20     type Encoding = &'static encoding_rs::Encoding;
21 
utf8() -> Self::Encoding22     fn utf8() -> Self::Encoding {
23         encoding_rs::UTF_8
24     }
25 
is_utf16_be_or_le(encoding: &Self::Encoding) -> bool26     fn is_utf16_be_or_le(encoding: &Self::Encoding) -> bool {
27         *encoding == encoding_rs::UTF_16LE || *encoding == encoding_rs::UTF_16BE
28     }
29 
from_label(ascii_label: &[u8]) -> Option<Self::Encoding>30     fn from_label(ascii_label: &[u8]) -> Option<Self::Encoding> {
31         encoding_rs::Encoding::for_label(ascii_label)
32     }
33 }
34 
decode_stylesheet_bytes<'a>( css: &'a [u8], protocol_encoding_label: Option<&str>, environment_encoding: Option<&'static encoding_rs::Encoding>, ) -> Cow<'a, str>35 fn 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 
50 impl 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`.
from_bytes( bytes: &[u8], url_data: UrlExtraData, protocol_encoding_label: Option<&str>, environment_encoding: Option<&'static encoding_rs::Encoding>, origin: Origin, media: MediaList, shared_lock: SharedRwLock, stylesheet_loader: Option<&dyn StylesheetLoader>, error_reporter: Option<&dyn ParseErrorReporter>, quirks_mode: QuirksMode, ) -> Stylesheet56     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             0,
79             AllowImportRules::Yes,
80         )
81     }
82 
83     /// Updates an empty stylesheet with a set of bytes that reached over the
84     /// network.
update_from_bytes( existing: &Stylesheet, bytes: &[u8], protocol_encoding_label: Option<&str>, environment_encoding: Option<&'static encoding_rs::Encoding>, url_data: UrlExtraData, stylesheet_loader: Option<&dyn StylesheetLoader>, error_reporter: Option<&dyn ParseErrorReporter>, )85     pub fn update_from_bytes(
86         existing: &Stylesheet,
87         bytes: &[u8],
88         protocol_encoding_label: Option<&str>,
89         environment_encoding: Option<&'static encoding_rs::Encoding>,
90         url_data: UrlExtraData,
91         stylesheet_loader: Option<&dyn StylesheetLoader>,
92         error_reporter: Option<&dyn ParseErrorReporter>,
93     ) {
94         let string = decode_stylesheet_bytes(bytes, protocol_encoding_label, environment_encoding);
95         Self::update_from_str(
96             existing,
97             &string,
98             url_data,
99             stylesheet_loader,
100             error_reporter,
101             0,
102             AllowImportRules::Yes,
103         )
104     }
105 }
106