## Coverage Report

#### Created: 2025-11-22 06:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /Users/andrewlamb/Software/datafusion/datafusion/expr/src/ptr_eq.rs

    Line
    Count
    Source
    1
    // Licensed to the Apache Software Foundation (ASF) under one
    2
    // or more contributor license agreements.  See the NOTICE file
    3
    // distributed with this work for additional information
    4
    // regarding copyright ownership.  The ASF licenses this file
    5
    // to you under the Apache License, Version 2.0 (the
    6
    // "License"); you may not use this file except in compliance
    7
    // with the License.  You may obtain a copy of the License at
    8
    //
    9
    //   http://www.apache.org/licenses/LICENSE-2.0
    10
    //
    11
    // Unless required by applicable law or agreed to in writing,
    12
    // software distributed under the License is distributed on an
    13
    // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14
    // KIND, either express or implied.  See the License for the
    15
    // specific language governing permissions and limitations
    16
    // under the License.
    17
    18
    use std::fmt::Debug;
    19
    use std::hash::{Hash, Hasher};
    20
    use std::ops::Deref;
    21
    use std::sync::Arc;
    22
    23
    /// Compares two `Arc` pointers for equality based on their underlying pointers values.
    24
    /// This is not equivalent to [`Arc::ptr_eq`] for fat pointers, see that method
    25
    /// for more information.
    26
    0
    pub fn arc_ptr_eq<T: ?Sized>(a: &Arc<T>, b: &Arc<T>) -> bool {
    27
    0
        std::ptr::eq(Arc::as_ptr(a), Arc::as_ptr(b))
    28
    0
    }
    29
    30
    /// Hashes an `Arc` pointer based on its underlying pointer value.
    31
    /// The general contract for this function is that if [`arc_ptr_eq`] returns `true`
    32
    /// for two `Arc`s, then this function should return the same hash value for both.
    33
    0
    pub fn arc_ptr_hash<T: ?Sized>(a: &Arc<T>, hasher: &mut impl Hasher) {
    34
    0
        std::ptr::hash(Arc::as_ptr(a), hasher)
    35
    0
    }
    36
    37
    /// A wrapper around a pointer that implements `Eq` and `Hash` comparing
    38
    /// the underlying pointer address.
    39
    ///
    40
    /// If you have pointers to a `dyn UDF impl` consider using [`super::udf_eq::UdfEq`].
    41
    #[derive(Clone)]
    42
    #[allow(private_bounds)] // This is so that PtrEq can only be used with allowed pointer types (e.g. Arc), without allowing misuse.
    43
    pub struct PtrEq<Ptr: PointerType>(Ptr);
    44
    45
    impl<T> PartialEq for PtrEq<Arc<T>>
    46
    where
    47
        T: ?Sized,
    48
    {
    49
    0
        fn eq(&self, other: &Self) -> bool {
    50
    0
            arc_ptr_eq(&self.0, &other.0)
    51
    0
        }
    52
    }
    53
    impl<T> Eq for PtrEq<Arc<T>> where T: ?Sized {}
    54
    55
    impl<T> Hash for PtrEq<Arc<T>>
    56
    where
    57
        T: ?Sized,
    58
    {
    59
    0
        fn hash<H: Hasher>(&self, state: &mut H) {
    60
    0
            arc_ptr_hash(&self.0, state);
    61
    0
        }
    62
    }
    63
    64
    impl<Ptr> From<Ptr> for PtrEq<Ptr>
    65
    where
    66
        Ptr: PointerType,
    67
    {
    68
    0
        fn from(ptr: Ptr) -> Self {
    69
    0
            PtrEq(ptr)
    70
    0
        }
    71
    }
    72
    73
    impl<T> From<PtrEq<Arc<T>>> for Arc<T>
    74
    where
    75
        T: ?Sized,
    76
    {
    77
    0
        fn from(wrapper: PtrEq<Arc<T>>) -> Self {
    78
    0
            wrapper.0
    79
    0
        }
    80
    }
    81
    82
    impl<Ptr> Debug for PtrEq<Ptr>
    83
    where
    84
        Ptr: PointerType + Debug,
    85
    {
    86
    0
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    87
    0
            self.0.fmt(f)
    88
    0
        }
    89
    }
    90
    91
    impl<Ptr> Deref for PtrEq<Ptr>
    92
    where
    93
        Ptr: PointerType,
    94
    {
    95
        type Target = Ptr;
    96
    97
    0
        fn deref(&self) -> &Self::Target {
    98
    0
            &self.0
    99
    0
        }
    100
    }
    101
    102
    trait PointerType {}
    103
    impl<T> PointerType for Arc<T> where T: ?Sized {}
    104
    105
    #[cfg(test)]
    106
    mod tests {
    107
        use super::*;
    108
        use std::hash::DefaultHasher;
    109
    110
        #[test]
    111
        pub fn test_ptr_eq_wrapper() {
    112
            let a = Arc::new("Hello".to_string());
    113
            let b = Arc::new(a.deref().clone());
    114
            let c = Arc::new("world".to_string());
    115
    116
            let wrapper = PtrEq(Arc::clone(&a));
    117
            assert_eq!(wrapper, wrapper);
    118
    119
            // same address (equal)
    120
            assert_eq!(PtrEq(Arc::clone(&a)), PtrEq(Arc::clone(&a)));
    121
            assert_eq!(hash(PtrEq(Arc::clone(&a))), hash(PtrEq(Arc::clone(&a))));
    122
    123
            // different address, same content (not equal)
    124
            assert_ne!(PtrEq(Arc::clone(&a)), PtrEq(Arc::clone(&b)));
    125
    126
            // different address, different content (not equal)
    127
            assert_ne!(PtrEq(Arc::clone(&a)), PtrEq(Arc::clone(&c)));
    128
        }
    129
    130
        fn hash<T: Hash>(value: T) -> u64 {
    131
            let hasher = &mut DefaultHasher::new();
    132
            value.hash(hasher);
    133
            hasher.finish()
    134
        }
    135
    }