1 | pub mod sk64 { |
2 | const SK_MAX_S32: i32 = std::i32::MAX; |
3 | const SK_MIN_S32: i32 = -SK_MAX_S32; |
4 | |
5 | pub fn pin_to_s32(x: i64) -> i32 { |
6 | if x < i64::from(SK_MIN_S32) { |
7 | return SK_MIN_S32; |
8 | } |
9 | if x > i64::from(SK_MAX_S32) { |
10 | return SK_MAX_S32; |
11 | } |
12 | x as i32 |
13 | } |
14 | } |
15 | |
16 | pub mod sk32 { |
17 | use super::sk64; |
18 | |
19 | pub fn sat_add(a: i32, b: i32) -> i32 { |
20 | sk64::pin_to_s32(i64::from(a) + i64::from(b)) |
21 | } |
22 | |
23 | pub fn sat_sub(a: i32, b: i32) -> i32 { |
24 | sk64::pin_to_s32(i64::from(a) - i64::from(b)) |
25 | } |
26 | |
27 | // The original Skia implementations were created |
28 | // to circumvent an LLVM sanitizer check, but do cause |
29 | // a "subtract with overflow" for simple cases (see testcase below), |
30 | // so we keep the naive implementation for now. |
31 | // Ref: |
32 | // https://skia-review.googlesource.com/c/skia/+/90544 |
33 | // https://skia-review.googlesource.com/c/skia/+/101881 |
34 | #[allow (dead_code)] |
35 | pub const fn can_overflow_add(a: i32, b: i32) -> i32 { |
36 | // ((a as u32) + (b as u32)) as i32 |
37 | a + b |
38 | } |
39 | |
40 | pub const fn can_overflow_sub(a: i32, b: i32) -> i32 { |
41 | // ((a as u32) - (b as u32)) as i32 |
42 | a - b |
43 | } |
44 | |
45 | #[test ] |
46 | fn subtraction_with_negative_does_not_overflow() { |
47 | can_overflow_sub(111, -257); |
48 | } |
49 | } |
50 | |