• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zbraniecki / icu4x / 11904027177

19 Nov 2024 12:33AM UTC coverage: 75.477% (+0.3%) from 75.174%
11904027177

push

github

web-flow
Move DateTimePattern into pattern module (#5834)

#1317

Also removes `NeoNeverMarker` and fixes #5689

258 of 319 new or added lines in 6 files covered. (80.88%)

6967 existing lines in 278 files now uncovered.

54522 of 72237 relevant lines covered (75.48%)

655305.49 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.78
/components/datetime/src/fields/mod.rs
1
// This file is part of ICU4X. For terms of use, please see the file
2
// called LICENSE at the top level of the ICU4X source tree
3
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4

5
//! Enums representing the fields in a date pattern, including the field's type, length and symbol.
6

7
#![allow(clippy::exhaustive_structs)] // Field and FieldULE part of data struct
8

9
mod length;
10
pub(crate) mod symbols;
11

12
use displaydoc::Display;
13
pub use length::{FieldLength, FieldNumericOverrides, LengthError};
14
pub use symbols::*;
15

16
#[cfg(any(feature = "experimental", feature = "datagen"))]
17
pub mod components;
18

19
use core::{
20
    cmp::{Ord, PartialOrd},
21
    convert::TryFrom,
22
};
23

24
/// An error relating to the field for a date pattern field as a whole.
25
///
26
/// Separate error types exist for parts of a field, like the
27
/// [`LengthError`](error for the field length) and the
28
/// [`SymbolError`](error for the field symbol).
UNCOV
29
#[derive(Display, Debug, Copy, Clone, PartialEq)]
×
30
#[non_exhaustive]
31
pub enum Error {
32
    /// An error originating inside of the [data provider](icu_provider).
33
    #[displaydoc("Field {0:?} is not a valid length")]
UNCOV
34
    InvalidLength(FieldSymbol),
×
35
}
36

37
#[cfg(feature = "std")]
38
impl std::error::Error for Error {}
39

40
/// A field within a date pattern string, also referred to as a date field.
41
///
42
/// A date field is the
43
/// repetition of a specific pattern character one or more times within the pattern string.
44
/// The pattern character is known as the field symbol, which indicates the particular meaning for the field.
45
#[derive(Debug, Eq, PartialEq, Clone, Copy, Ord, PartialOrd)]
4,702,568✔
46
#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
10✔
47
#[cfg_attr(feature = "datagen", databake(path = icu_datetime::fields))]
48
#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
10✔
49
#[zerovec::make_ule(FieldULE)]
13✔
50
pub struct Field {
51
    /// The field symbol for the `Field`, which corresponds to the field's meaning with the
52
    /// date pattern.
53
    pub symbol: FieldSymbol,
2,351,284✔
54
    /// The length of the `Field`, which in conjunction with the `FieldSymbol` informs the width or
55
    /// style of the formatting output corresponding to this field.
56
    pub length: FieldLength,
1,302,733✔
57
}
58

59
impl Field {
60
    #[cfg(feature = "datagen")]
61
    pub(crate) fn get_length_type(&self) -> TextOrNumeric {
669,868✔
62
        match self.symbol {
669,868✔
63
            FieldSymbol::Era => TextOrNumeric::Text,
36,528✔
64
            FieldSymbol::Year(year) => year.get_length_type(self.length),
68,180✔
65
            FieldSymbol::Month(month) => month.get_length_type(self.length),
174,712✔
66
            FieldSymbol::Week(week) => week.get_length_type(self.length),
669,868✔
67
            FieldSymbol::Day(day) => day.get_length_type(self.length),
26,546✔
68
            FieldSymbol::Weekday(weekday) => weekday.get_length_type(self.length),
54,560✔
UNCOV
69
            FieldSymbol::DayPeriod(day_period) => day_period.get_length_type(self.length),
×
70
            FieldSymbol::Hour(hour) => hour.get_length_type(self.length),
44,058✔
71
            FieldSymbol::Minute => TextOrNumeric::Numeric,
186,968✔
72
            FieldSymbol::Second(second) => second.get_length_type(self.length),
78,316✔
UNCOV
73
            FieldSymbol::TimeZone(zone) => zone.get_length_type(self.length),
×
UNCOV
74
            FieldSymbol::DecimalSecond(_) => TextOrNumeric::Numeric,
×
75
        }
76
    }
669,868✔
77
}
78

79
impl FieldULE {
80
    #[inline]
81
    pub(crate) fn validate_byte_pair(bytes: (u8, u8)) -> Result<(), zerovec::ule::UleError> {
40,877✔
82
        symbols::FieldSymbolULE::validate_byte(bytes.0)?;
40,877✔
83
        length::FieldLengthULE::validate_byte(bytes.1)?;
40,877✔
84
        Ok(())
40,877✔
85
    }
40,877✔
86
}
87

88
impl From<(FieldSymbol, FieldLength)> for Field {
89
    fn from(input: (FieldSymbol, FieldLength)) -> Self {
540,242✔
90
        Self {
540,242✔
91
            symbol: input.0,
540,242✔
92
            length: input.1,
540,242✔
93
        }
94
    }
540,242✔
95
}
96

97
impl TryFrom<(FieldSymbol, usize)> for Field {
98
    type Error = Error;
99
    fn try_from(input: (FieldSymbol, usize)) -> Result<Self, Self::Error> {
×
100
        let length = FieldLength::from_idx(input.1 as u8)
×
101
            .map_err(|_| Self::Error::InvalidLength(input.0))?;
×
UNCOV
102
        Ok(Self {
×
103
            symbol: input.0,
×
104
            length,
105
        })
106
    }
×
107
}
108

109
#[cfg(test)]
110
mod test {
111
    use super::*;
112
    use crate::fields::{Field, FieldLength, FieldSymbol, Second, Year};
113
    use zerovec::ule::{AsULE, ULE};
114

115
    #[test]
116
    fn test_field_as_ule() {
2✔
117
        let samples = [
1✔
118
            (
1✔
119
                Field::from((FieldSymbol::Minute, FieldLength::Two)),
1✔
120
                [FieldSymbol::Minute.idx(), FieldLength::Two.idx()],
1✔
121
            ),
122
            (
1✔
123
                Field::from((FieldSymbol::Year(Year::Calendar), FieldLength::Four)),
1✔
124
                [
1✔
125
                    FieldSymbol::Year(Year::Calendar).idx(),
1✔
126
                    FieldLength::Four.idx(),
1✔
127
                ],
128
            ),
129
            (
1✔
130
                Field::from((FieldSymbol::Year(Year::Cyclic), FieldLength::Four)),
1✔
131
                [
1✔
132
                    FieldSymbol::Year(Year::Cyclic).idx(),
1✔
133
                    FieldLength::Four.idx(),
1✔
134
                ],
135
            ),
136
            (
1✔
137
                Field::from((FieldSymbol::Second(Second::MillisInDay), FieldLength::One)),
1✔
138
                [
1✔
139
                    FieldSymbol::Second(Second::MillisInDay).idx(),
1✔
140
                    FieldLength::One.idx(),
1✔
141
                ],
142
            ),
143
        ];
144

145
        for (ref_field, ref_bytes) in samples {
5✔
146
            let ule = ref_field.to_unaligned();
4✔
147
            assert_eq!(ULE::slice_as_bytes(&[ule]), ref_bytes);
4✔
148
            let field = Field::from_unaligned(ule);
4✔
149
            assert_eq!(field, ref_field);
4✔
150
        }
1✔
151
    }
2✔
152

153
    #[test]
154
    fn test_field_ule() {
2✔
155
        let samples = [(
1✔
156
            [
1✔
157
                Field::from((FieldSymbol::Year(Year::Calendar), FieldLength::Four)),
1✔
158
                Field::from((FieldSymbol::Second(Second::MillisInDay), FieldLength::One)),
1✔
159
            ],
160
            [
1✔
161
                [
1✔
162
                    FieldSymbol::Year(Year::Calendar).idx(),
1✔
163
                    FieldLength::Four.idx(),
1✔
164
                ],
165
                [
1✔
166
                    FieldSymbol::Second(Second::MillisInDay).idx(),
1✔
167
                    FieldLength::One.idx(),
1✔
168
                ],
169
            ],
170
        )];
171

172
        for (ref_field, ref_bytes) in samples {
1✔
173
            let mut bytes: Vec<u8> = vec![];
1✔
174
            for item in ref_field.iter() {
3✔
175
                let ule = item.to_unaligned();
2✔
176
                bytes.extend(ULE::slice_as_bytes(&[ule]));
2✔
177
            }
178

179
            let mut bytes2: Vec<u8> = vec![];
1✔
180
            for seq in ref_bytes.iter() {
3✔
181
                bytes2.extend_from_slice(seq);
2✔
182
            }
183

184
            assert!(FieldULE::validate_bytes(&bytes).is_ok());
1✔
185
            assert_eq!(bytes, bytes2);
1✔
186
        }
2✔
187
    }
2✔
188
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc