Coverage Report

Created: 2026-06-30 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}