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