<commit_before>// Copyright 2022 The ChromiumOS Authors.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cmp;
use std::ops::RangeInclusive;

use serde::{Deserialize, Serialize};

#[derive(Copy, Clone, Debug)]
/// Represents a range of addresses from `start` to `end`, inclusive.
///
/// Why not use the standard `RangeInclusive`? `RangeInclusive` is not `Copy`, because it tries to
/// be an iterator as well as a range (which also means it is larger than necessary). Additionally,
/// we would also like to implement some convenience functions for our own type.
#[derive(Deserialize, Serialize)]
pub struct AddressRange {
    pub start: u64,
    pub end: u64,
}

impl AddressRange {
    /// Creates a new `AddressRange` from `start` and `end` (inclusive) addresses.
    pub const fn from_start_and_end(start: u64, end: u64) -> Self {
        AddressRange { start, end }
    }

    /// Creates a new `AddressRange` from `start` extending `size` bytes.
    ///
    /// Returns `None` if the generated range is not representable as an `AddressRange`.
    pub const fn from_start_and_size(start: u64, size: u64) -> Option<Self> {
        if size == 0 {
            Some(AddressRange::empty())
        } else if let Some(end) = start.checked_add(size - 1) {
            Some(AddressRange { start, end })
        } else {
            None
        }
    }

    /// Returns an empty range.
    pub const fn empty() -> Self {
        AddressRange { start: 1, end: 0 }
    }

    /// Returns `true` if this range is empty (contains no addresses).
    pub fn is_empty(&self) -> bool {
        self.end < self.start
    }

    /// Returns `true` if this range contains `address`.
    pub fn contains(&self, address: u64) -> bool {
        address >= self.start && address <= self.end
    }

    /// Returns `true` if `other` is fully contained within this range.
    ///
    /// Empty ranges are considered to be not contained by any range.
    pub fn contains_range(&self, other: AddressRange) -> bool {
        !other.is_empty() && other.start >= self.start && other.end <= self.end
    }

    /// Returns `true` if the two ranges have any addresses in common.
    pub fn overlaps(&self, other: AddressRange) -> bool {
        !self.intersect(other).is_empty()
    }

    /// Find the intersection (overlapping region) of two ranges.
    ///
    /// If there is no intersection, the resulting `AddressRange` will be empty.
    pub fn intersect(&self, other: AddressRange) -> AddressRange {
        let start = cmp::max(self.start, other.start);
        let end = cmp::min(self.end, other.end);
        AddressRange { start, end }
    }

    /// Returns the ranges of addresses contained in `self` but not in `other`.
    ///
    /// The first returned range will contain the addresses in `self` that are less than the start
    /// of `other`, which will be empty if the starts of the ranges coincide.
    ///
    /// The second returned range will contain the addresses in `self` that are greater than the end
    /// of `other`, which will be empty if the ends of the ranges coincide.
    pub fn non_overlapping_ranges(&self, other: AddressRange) -> (AddressRange, AddressRange) {
        let before = if self.start >= other.start {
            Self::empty()
        } else {
            let start = cmp::min(self.start, other.start);

            // We know that self.start != other.start, so the maximum of the two cannot be 0, so it
            // is safe to subtract 1.
            let end = cmp::max(self.start, other.start) - 1;

            // For non-overlapping ranges, don't allow end to extend past self.end.
            let end = cmp::min(end, self.end);

            AddressRange { start, end }
        };

        let after = if self.end <= other.end {
            Self::empty()
        } else {
            // We know that self.end != other.end, so the minimum of the two cannot be `u64::MAX`,
            // so it is safe to add 1.
            let start = cmp::min(self.end, other.end) + 1;

            // For non-overlapping ranges, don't allow start to extend before self.start.
            let start = cmp::max(start, self.start);

            let end = cmp::max(self.end, other.end);

            AddressRange { start, end }
        };

        (before, after)
    }

    /// Returns the two subsets of this range split at the `split_start` address.
    ///
    /// If `split_start` is not contained in this range, returns the original range and an empty
    /// range.
    pub fn split_at(&self, split_start: u64) -> (AddressRange, AddressRange) {
        // split_start == self.start is handled as a special case so we know that split_start - 1 is
        // safe below (and so the empty range is always returned second if present).
        if split_start <= self.start || split_start > self.end {
            (*self, Self::empty())
        } else {
            (
                AddressRange {
                    start: self.start,
                    end: split_start - 1,
                },
                AddressRange {
                    start: split_start,
                    end: self.end,
                },
            )
        }
    }

    /// Computes the length of an `AddressRange`.
    ///
    /// Returns `None` if the length cannot be represented in `u64` (if the range is
    /// `0..=u64::MAX`).
    pub fn len(&self) -> Option<u64> {
        // Treat any range we consider "empty" (end < start) as having 0 length.
        if self.is_empty() {
            Some(0)
        } else {
            (self.end - self.start).checked_add(1)
        }
    }
}

impl std::fmt::Display for AddressRange {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        if self.is_empty() {
            f.write_str("empty")
        } else {
            f.write_fmt(format_args!("{:#x}..={:#x}", self.start, self.end))
        }
    }
}

impl From<RangeInclusive<u64>> for AddressRange {
    fn from(range: RangeInclusive<u64>) -> AddressRange {
        AddressRange {
            start: *range.start(),
            end: *range.end(),
        }
    }
}

impl From<AddressRange> for RangeInclusive<u64> {
    fn from(address_range: AddressRange) -> RangeInclusive<u64> {
        address_range.start..=address_range.end<commit_msg>resources: implement Debug for AddressRange<commit_after>// Copyright 2022 The ChromiumOS Authors.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cmp;
use std::ops::RangeInclusive;

use serde::{Deserialize, Serialize};

/// Represents a range of addresses from `start` to `end`, inclusive.
///
/// Why not use the standard `RangeInclusive`? `RangeInclusive` is not `Copy`, because it tries to
/// be an iterator as well as a range (which also means it is larger than necessary). Additionally,
/// we would also like to implement some convenience functions for our own type.
#[derive(Copy, Clone, Deserialize, Serialize)]
pub struct AddressRange {
    pub start: u64,
    pub end: u64,
}

impl AddressRange {
    /// Creates a new `AddressRange` from `start` and `end` (inclusive) addresses.
    pub const fn from_start_and_end(start: u64, end: u64) -> Self {
        AddressRange { start, end }
    }

    /// Creates a new `AddressRange` from `start` extending `size` bytes.
    ///
    /// Returns `None` if the generated range is not representable as an `AddressRange`.
    pub const fn from_start_and_size(start: u64, size: u64) -> Option<Self> {
        if size == 0 {
            Some(AddressRange::empty())
        } else if let Some(end) = start.checked_add(size - 1) {
            Some(AddressRange { start, end })
        } else {
            None
        }
    }

    /// Returns an empty range.
    pub const fn empty() -> Self {
        AddressRange { start: 1, end: 0 }
    }

    /// Returns `true` if this range is empty (contains no addresses).
    pub fn is_empty(&self) -> bool {
        self.end < self.start
    }

    /// Returns `true` if this range contains `address`.
    pub fn contains(&self, address: u64) -> bool {
        address >= self.start && address <= self.end
    }

    /// Returns `true` if `other` is fully contained within this range.
    ///
    /// Empty ranges are considered to be not contained by any range.
    pub fn contains_range(&self, other: AddressRange) -> bool {
        !other.is_empty() && other.start >= self.start && other.end <= self.end
    }

    /// Returns `true` if the two ranges have any addresses in common.
    pub fn overlaps(&self, other: AddressRange) -> bool {
        !self.intersect(other).is_empty()
    }

    /// Find the intersection (overlapping region) of two ranges.
    ///
    /// If there is no intersection, the resulting `AddressRange` will be empty.
    pub fn intersect(&self, other: AddressRange) -> AddressRange {
        let start = cmp::max(self.start, other.start);
        let end = cmp::min(self.end, other.end);
        AddressRange { start, end }
    }

    /// Returns the ranges of addresses contained in `self` but not in `other`.
    ///
    /// The first returned range will contain the addresses in `self` that are less than the start
    /// of `other`, which will be empty if the starts of the ranges coincide.
    ///
    /// The second returned range will contain the addresses in `self` that are greater than the end
    /// of `other`, which will be empty if the ends of the ranges coincide.
    pub fn non_overlapping_ranges(&self, other: AddressRange) -> (AddressRange, AddressRange) {
        let before = if self.start >= other.start {
            Self::empty()
        } else {
            let start = cmp::min(self.start, other.start);

            // We know that self.start != other.start, so the maximum of the two cannot be 0, so it
            // is safe to subtract 1.
            let end = cmp::max(self.start, other.start) - 1;

            // For non-overlapping ranges, don't allow end to extend past self.end.
            let end = cmp::min(end, self.end);

            AddressRange { start, end }
        };

        let after = if self.end <= other.end {
            Self::empty()
        } else {
            // We know that self.end != other.end, so the minimum of the two cannot be `u64::MAX`,
            // so it is safe to add 1.
            let start = cmp::min(self.end, other.end) + 1;

            // For non-overlapping ranges, don't allow start to extend before self.start.
            let start = cmp::max(start, self.start);

            let end = cmp::max(self.end, other.end);

            AddressRange { start, end }
        };

        (before, after)
    }

    /// Returns the two subsets of this range split at the `split_start` address.
    ///
    /// If `split_start` is not contained in this range, returns the original range and an empty
    /// range.
    pub fn split_at(&self, split_start: u64) -> (AddressRange, AddressRange) {
        // split_start == self.start is handled as a special case so we know that split_start - 1 is
        // safe below (and so the empty range is always returned second if present).
        if split_start <= self.start || split_start > self.end {
            (*self, Self::empty())
        } else {
            (
                AddressRange {
                    start: self.start,
                    end: split_start - 1,
                },
                AddressRange {
                    start: split_start,
                    end: self.end,
                },
            )
        }
    }

    /// Computes the length of an `AddressRange`.
    ///
    /// Returns `None` if the length cannot be represented in `u64` (if the range is
    /// `0..=u64::MAX`).
    pub fn len(&self) -> Option<u64> {
        // Treat any range we consider "empty" (end < start) as having 0 length.
        if self.is_empty() {
            Some(0)
        } else {
            (self.end - self.start).checked_add(1)
        }
    }

    fn log(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        if self.is_empty() {
            f.write_str("empty")
        } else {
            f.write_fmt(format_args!("{:#x}..={:#x}", self.start, self.end))
        }
    }
}

impl std::fmt::Display for AddressRange {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.log(f)
    }
}

impl std::fmt::Debug for AddressRange {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.log(f)
    }
}

impl From<RangeInclusive<u64>> for AddressRange {
    fn from(range: RangeInclusive<u64>) -> AddressRange {
        AddressRange {
            start: *range.start(),
            end: *range.end(),
        }
    }
}

impl From<AddressRange> for RangeInclusive<u64> {
    fn from(address_range: AddressRange) -> RangeInclusive<u64> {
        address_range.start..=address_range.end
{'fraction_non_alphanumeric': 0.12094463801780875, 'fraction_numerical': 0.007897793263646922, 'mean_word_length': 2.054872280037843, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2205696', 'n_tokens_mistral': 3776, 'n_tokens_neox': 3646, 'n_words': 1328}