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)]
94#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
95pub struct Range {
96    pub start: u32,
97    pub end: u32,
98}
99
100impl Range {
101    /// The start, as `usize`
102    pub fn start(self) -> usize {
103        to_usize(self.start)
104    }
105
106    /// The end, as `usize`
107    pub fn end(self) -> usize {
108        to_usize(self.end)
109    }
110
111    /// True if the range is empty
112    pub fn is_empty(self) -> bool {
113        self.start >= self.end
114    }
115
116    /// The number of iterable items, as `usize`
117    pub fn len(self) -> usize {
118        to_usize(self.end) - to_usize(self.start)
119    }
120
121    /// True if the given value is contained, inclusive of end points
122    pub fn includes(self, value: usize) -> bool {
123        to_usize(self.start) <= value && value <= to_usize(self.end)
124    }
125
126    /// Convert to a standard range
127    pub fn to_std(self) -> std::ops::Range<usize> {
128        to_usize(self.start)..to_usize(self.end)
129    }
130
131    /// Convert to `usize` and iterate
132    pub fn iter(self) -> impl Iterator<Item = usize> {
133        self.to_std()
134    }
135}
136
137impl std::ops::Index<Range> for String {
138    type Output = str;
139
140    fn index(&self, range: Range) -> &str {
141        let range = std::ops::Range::<usize>::from(range);
142        &self[range]
143    }
144}
145
146impl std::ops::Index<Range> for str {
147    type Output = str;
148
149    fn index(&self, range: Range) -> &str {
150        let range = std::ops::Range::<usize>::from(range);
151        &self[range]
152    }
153}
154
155impl<T> std::ops::Index<Range> for [T] {
156    type Output = [T];
157
158    fn index(&self, range: Range) -> &[T] {
159        let range = std::ops::Range::<usize>::from(range);
160        &self[range]
161    }
162}
163
164impl std::ops::IndexMut<Range> for String {
165    fn index_mut(&mut self, range: Range) -> &mut str {
166        let range = std::ops::Range::<usize>::from(range);
167        &mut self[range]
168    }
169}
170
171impl std::ops::IndexMut<Range> for str {
172    fn index_mut(&mut self, range: Range) -> &mut str {
173        let range = std::ops::Range::<usize>::from(range);
174        &mut self[range]
175    }
176}
177
178impl<T> std::ops::IndexMut<Range> for [T] {
179    fn index_mut(&mut self, range: Range) -> &mut [T] {
180        let range = std::ops::Range::<usize>::from(range);
181        &mut self[range]
182    }
183}
184
185impl From<Range> for std::ops::Range<usize> {
186    fn from(range: Range) -> std::ops::Range<usize> {
187        to_usize(range.start)..to_usize(range.end)
188    }
189}
190
191impl From<std::ops::Range<u32>> for Range {
192    fn from(range: std::ops::Range<u32>) -> Range {
193        Range {
194            start: range.start,
195            end: range.end,
196        }
197    }
198}
199
200impl From<std::ops::Range<usize>> for Range {
201    fn from(range: std::ops::Range<usize>) -> Range {
202        Range {
203            start: to_u32(range.start),
204            end: to_u32(range.end),
205        }
206    }
207}