Coverage Report

Created: 2025-11-28 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/flatbuffers-25.2.10/src/array.rs
Line
Count
Source
1
/*
2
 * Copyright 2021 Google Inc. All rights reserved.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
use crate::follow::Follow;
18
use crate::vector::VectorIter;
19
use crate::EndianScalar;
20
use core::fmt::{Debug, Formatter, Result};
21
use core::marker::PhantomData;
22
use core::mem::size_of;
23
24
#[derive(Copy, Clone)]
25
pub struct Array<'a, T: 'a, const N: usize>(&'a [u8], PhantomData<T>);
26
27
impl<'a, T: 'a, const N: usize> Debug for Array<'a, T, N>
28
where
29
    T: 'a + Follow<'a>,
30
    <T as Follow<'a>>::Inner: Debug,
31
{
32
0
    fn fmt(&self, f: &mut Formatter) -> Result {
33
0
        f.debug_list().entries(self.iter()).finish()
34
0
    }
35
}
36
37
#[allow(clippy::len_without_is_empty)]
38
#[allow(clippy::from_over_into)] // TODO(caspern): Go from From to Into.
39
impl<'a, T: 'a, const N: usize> Array<'a, T, N> {
40
    /// # Safety
41
    ///
42
    /// buf must be a contiguous array of `T`
43
    ///
44
    /// # Panics
45
    ///
46
    /// Panics if `buf.len()` is not `size_of::<T>() * N`
47
    #[inline(always)]
48
0
    pub unsafe fn new(buf: &'a [u8]) -> Self {
49
0
        assert_eq!(size_of::<T>() * N, buf.len());
50
51
0
        Array(buf, PhantomData)
52
0
    }
53
54
    #[inline(always)]
55
0
    pub const fn len(&self) -> usize {
56
0
        N
57
0
    }
58
0
    pub fn as_ptr(&self) -> *const u8 {
59
0
        self.0.as_ptr()
60
0
    }
61
}
62
63
impl<'a, T: Follow<'a> + 'a, const N: usize> Array<'a, T, N> {
64
    #[inline(always)]
65
0
    pub fn get(&self, idx: usize) -> T::Inner {
66
0
        assert!(idx < N);
67
0
        let sz = size_of::<T>();
68
        // Safety:
69
        // self.0 was valid for length `N` on construction and have verified `idx < N`
70
0
        unsafe { T::follow(self.0, sz * idx) }
71
0
    }
72
73
    #[inline(always)]
74
0
    pub fn iter(&self) -> VectorIter<'a, T> {
75
        // Safety:
76
        // self.0 was valid for length N on construction
77
0
        unsafe { VectorIter::from_slice(self.0, self.len()) }
78
0
    }
79
}
80
81
impl<'a, T: Follow<'a> + Debug, const N: usize> From<Array<'a, T, N>> for [T::Inner; N] {
82
0
    fn from(array: Array<'a, T, N>) -> Self {
83
0
        array_init(|i| array.get(i))
84
0
    }
85
}
86
87
/// Implement Follow for all possible Arrays that have Follow-able elements.
88
impl<'a, T: Follow<'a> + 'a, const N: usize> Follow<'a> for Array<'a, T, N> {
89
    type Inner = Array<'a, T, N>;
90
    #[inline(always)]
91
0
    unsafe fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
92
0
        Array::new(&buf[loc..loc + N * size_of::<T>()])
93
0
    }
94
}
95
96
/// Place an array of EndianScalar into the provided mutable byte slice. Performs
97
/// endian conversion, if necessary.
98
/// # Safety
99
/// Caller must ensure `s.len() >= size_of::<[T; N]>()`
100
0
pub unsafe fn emplace_scalar_array<T: EndianScalar, const N: usize>(
101
0
    buf: &mut [u8],
102
0
    loc: usize,
103
0
    src: &[T; N],
104
0
) {
105
0
    let mut buf_ptr = buf[loc..].as_mut_ptr();
106
0
    for item in src.iter() {
107
0
        let item_le = item.to_little_endian();
108
0
        core::ptr::copy_nonoverlapping(
109
0
            &item_le as *const T::Scalar as *const u8,
110
0
            buf_ptr,
111
0
            size_of::<T::Scalar>(),
112
0
        );
113
0
        buf_ptr = buf_ptr.add(size_of::<T::Scalar>());
114
0
    }
115
0
}
116
117
impl<'a, T: Follow<'a> + 'a, const N: usize> IntoIterator for Array<'a, T, N> {
118
    type Item = T::Inner;
119
    type IntoIter = VectorIter<'a, T>;
120
    #[inline]
121
0
    fn into_iter(self) -> Self::IntoIter {
122
0
        self.iter()
123
0
    }
124
}
125
126
#[inline]
127
0
pub fn array_init<F, T, const N: usize>(mut initializer: F) -> [T; N]
128
0
where
129
0
    F: FnMut(usize) -> T,
130
{
131
0
    let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit();
132
0
    let mut ptr_i = array.as_mut_ptr() as *mut T;
133
134
    // Safety:
135
    // array is aligned by T, and has length N
136
    unsafe {
137
0
        for i in 0..N {
138
0
            let value_i = initializer(i);
139
0
            ptr_i.write(value_i);
140
0
            ptr_i = ptr_i.add(1);
141
0
        }
142
0
        array.assume_init()
143
    }
144
0
}
145
146
#[cfg(feature = "serialize")]
147
impl<'a, T: 'a, const N: usize> serde::ser::Serialize for Array<'a, T, N>
148
where
149
    T: 'a + Follow<'a>,
150
    <T as Follow<'a>>::Inner: serde::ser::Serialize,
151
{
152
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
153
    where
154
        S: serde::ser::Serializer,
155
    {
156
        use serde::ser::SerializeSeq;
157
        let mut seq = serializer.serialize_seq(Some(self.len()))?;
158
        for element in self.iter() {
159
            seq.serialize_element(&element)?;
160
        }
161
        seq.end()
162
    }
163
}