Skip to main content

kas_text/
data.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! KAS Rich-Text library — simple data types
7
8use crate::conv::{to_u32, to_usize};
9
10/// 2D vector (position/size/offset) over `f32`
11#[derive(Clone, Copy, Debug, Default, PartialEq)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Vec2(pub f32, pub f32);
14
15impl Vec2 {
16    /// Zero
17    pub const ZERO: Vec2 = Vec2(0.0, 0.0);
18
19    /// Positive infinity
20    pub const INFINITY: Vec2 = Vec2(f32::INFINITY, f32::INFINITY);
21
22    /// Take the absolute value of each component
23    #[inline]
24    pub fn abs(self) -> Self {
25        Vec2(self.0.abs(), self.1.abs())
26    }
27
28    /// Return the minimum, component-wise
29    #[inline]
30    pub fn min(self, other: Self) -> Self {
31        Vec2(self.0.min(other.0), self.1.min(other.1))
32    }
33
34    /// Return the maximum, component-wise
35    #[inline]
36    pub fn max(self, other: Self) -> Self {
37        Vec2(self.0.max(other.0), self.1.max(other.1))
38    }
39
40    /// Whether both components are finite
41    #[inline]
42    pub fn is_finite(self) -> bool {
43        self.0.is_finite() && self.1.is_finite()
44    }
45}
46
47impl std::ops::Add for Vec2 {
48    type Output = Self;
49
50    #[inline]
51    fn add(self, other: Self) -> Self {
52        Vec2(self.0 + other.0, self.1 + other.1)
53    }
54}
55impl std::ops::AddAssign for Vec2 {
56    #[inline]
57    fn add_assign(&mut self, rhs: Self) {
58        self.0 += rhs.0;
59        self.1 += rhs.1;
60    }
61}
62
63impl std::ops::Sub for Vec2 {
64    type Output = Self;
65
66    #[inline]
67    fn sub(self, other: Self) -> Self {
68        Vec2(self.0 - other.0, self.1 - other.1)
69    }
70}
71impl std::ops::SubAssign for Vec2 {
72    #[inline]
73    fn sub_assign(&mut self, rhs: Self) {
74        self.0 -= rhs.0;
75        self.1 -= rhs.1;
76    }
77}
78
79impl From<Vec2> for (f32, f32) {
80    fn from(size: Vec2) -> Self {
81        (size.0, size.1)
82    }
83}
84
85/// Range type
86///
87/// Essentially this is just a `std::ops::Range<u32>`, but with convenient
88/// implementations.
89///
90/// Note that we consider `u32` large enough for any text we wish to display
91/// and the library is too complex to be useful on 16-bit CPUs, so using `u32`
92/// makes more sense than `usize`.
93#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
94pub struct Range {
95    pub start: u32,
96    pub end: u32,
97}
98
99impl Range {
100    /// The start, as `usize`
101    pub fn start(self) -> usize {
102        to_usize(self.start)
103    }
104
105    /// The end, as `usize`
106    pub fn end(self) -> usize {
107        to_usize(self.end)
108    }
109
110    /// True if the range is empty
111    pub fn is_empty(self) -> bool {
112        self.start >= self.end
113    }
114
115    /// The number of iterable items, as `usize`
116    pub fn len(self) -> usize {
117        to_usize(self.end) - to_usize(self.start)
118    }
119
120    /// Convert to a standard range
121    pub fn to_std(self) -> std::ops::Range<usize> {
122        to_usize(self.start)..to_usize(self.end)
123    }
124
125    /// Convert to `usize` and iterate
126    pub fn iter(self) -> impl Iterator<Item = usize> {
127        self.to_std()
128    }
129}
130
131impl std::ops::Index<Range> for String {
132    type Output = str;
133
134    fn index(&self, range: Range) -> &str {
135        let range = std::ops::Range::<usize>::from(range);
136        &self[range]
137    }
138}
139
140impl std::ops::Index<Range> for str {
141    type Output = str;
142
143    fn index(&self, range: Range) -> &str {
144        let range = std::ops::Range::<usize>::from(range);
145        &self[range]
146    }
147}
148
149impl<T> std::ops::Index<Range> for [T] {
150    type Output = [T];
151
152    fn index(&self, range: Range) -> &[T] {
153        let range = std::ops::Range::<usize>::from(range);
154        &self[range]
155    }
156}
157
158impl std::ops::IndexMut<Range> for String {
159    fn index_mut(&mut self, range: Range) -> &mut str {
160        let range = std::ops::Range::<usize>::from(range);
161        &mut self[range]
162    }
163}
164
165impl std::ops::IndexMut<Range> for str {
166    fn index_mut(&mut self, range: Range) -> &mut str {
167        let range = std::ops::Range::<usize>::from(range);
168        &mut self[range]
169    }
170}
171
172impl<T> std::ops::IndexMut<Range> for [T] {
173    fn index_mut(&mut self, range: Range) -> &mut [T] {
174        let range = std::ops::Range::<usize>::from(range);
175        &mut self[range]
176    }
177}
178
179impl From<Range> for std::ops::Range<usize> {
180    fn from(range: Range) -> std::ops::Range<usize> {
181        to_usize(range.start)..to_usize(range.end)
182    }
183}
184
185impl From<std::ops::Range<u32>> for Range {
186    fn from(range: std::ops::Range<u32>) -> Range {
187        Range {
188            start: range.start,
189            end: range.end,
190        }
191    }
192}
193
194impl From<std::ops::Range<usize>> for Range {
195    fn from(range: std::ops::Range<usize>) -> Range {
196        Range {
197            start: to_u32(range.start),
198            end: to_u32(range.end),
199        }
200    }
201}