/rust/registry/src/index.crates.io-1949cf8c6b5b557f/cssparser-0.35.0/src/from_bytes.rs
Line | Count | Source |
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 | | /// Abstraction for avoiding a dependency from cssparser to an encoding library |
6 | | pub trait EncodingSupport { |
7 | | /// One character encoding |
8 | | type Encoding; |
9 | | |
10 | | /// https://encoding.spec.whatwg.org/#concept-encoding-get |
11 | | fn from_label(ascii_label: &[u8]) -> Option<Self::Encoding>; |
12 | | |
13 | | /// Return the UTF-8 encoding |
14 | | fn utf8() -> Self::Encoding; |
15 | | |
16 | | /// Whether the given encoding is UTF-16BE or UTF-16LE |
17 | | fn is_utf16_be_or_le(encoding: &Self::Encoding) -> bool; |
18 | | } |
19 | | |
20 | | /// Determine the character encoding of a CSS stylesheet. |
21 | | /// |
22 | | /// This is based on the presence of a BOM (Byte Order Mark), an `@charset` rule, and |
23 | | /// encoding meta-information. |
24 | | /// |
25 | | /// * `css_bytes`: A byte string. |
26 | | /// * `protocol_encoding`: The encoding label, if any, defined by HTTP or equivalent protocol. |
27 | | /// (e.g. via the `charset` parameter of the `Content-Type` header.) |
28 | | /// * `environment_encoding`: An optional `Encoding` object for the [environment encoding] |
29 | | /// (https://drafts.csswg.org/css-syntax/#environment-encoding), if any. |
30 | | /// |
31 | | /// Returns the encoding to use. |
32 | 0 | pub fn stylesheet_encoding<E>( |
33 | 0 | css: &[u8], |
34 | 0 | protocol_encoding_label: Option<&[u8]>, |
35 | 0 | environment_encoding: Option<E::Encoding>, |
36 | 0 | ) -> E::Encoding |
37 | 0 | where |
38 | 0 | E: EncodingSupport, |
39 | | { |
40 | | // https://drafts.csswg.org/css-syntax/#the-input-byte-stream |
41 | 0 | if let Some(label) = protocol_encoding_label { |
42 | 0 | if let Some(protocol_encoding) = E::from_label(label) { |
43 | 0 | return protocol_encoding; |
44 | 0 | }; |
45 | 0 | }; |
46 | | |
47 | 0 | let prefix = b"@charset \""; |
48 | 0 | if css.starts_with(prefix) { |
49 | 0 | let rest = &css[prefix.len()..]; |
50 | 0 | if let Some(label_length) = rest.iter().position(|&b| b == b'"') { |
51 | 0 | if rest[label_length..].starts_with(b"\";") { |
52 | 0 | let label = &rest[..label_length]; |
53 | 0 | if let Some(charset_encoding) = E::from_label(label) { |
54 | 0 | if E::is_utf16_be_or_le(&charset_encoding) { |
55 | 0 | return E::utf8(); |
56 | | } else { |
57 | 0 | return charset_encoding; |
58 | | } |
59 | 0 | } |
60 | 0 | } |
61 | 0 | } |
62 | 0 | } |
63 | 0 | environment_encoding.unwrap_or_else(E::utf8) |
64 | 0 | } |