diff --git a/CHANGELOG.md b/CHANGELOG.md index 220ddaf..e33c214 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.4.4 + +- Updated `FixedSizeList` to act more like a proper `List` + ## 1.4.3 - [FIX] Ensure that `FixedSizeList` takes any type of object. diff --git a/lib/src/classes/fixed_size_list.dart b/lib/src/classes/fixed_size_list.dart index 24083bc..4e3046a 100644 --- a/lib/src/classes/fixed_size_list.dart +++ b/lib/src/classes/fixed_size_list.dart @@ -1,29 +1,268 @@ +import "dart:math" show Random; + /// Represents a `List` with a fixed capacity. /// /// When a new element is added and the list reaches its maximum capacity, /// the oldest element in the list is automatically removed to make space. -class FixedSizeList { +class FixedSizeList implements List { final int _capacity; - final List _list; + final List _list; /// Creates a [FixedSizeList] with the specified [capacity]. /// /// The initial list will be empty. - FixedSizeList(this._capacity) : _list = []; + FixedSizeList(this._capacity, {List? list}) : _list = list ?? []; /// Adds a new [element] to the list. /// /// If the list is already at its maximum [capacity], the oldest element /// will be removed before the new [element] is added. - void add(T? element) { + @override + void add(T element) { _list.add(element); if (_list.length > _capacity) { _list.removeAt(0); } } + factory FixedSizeList.filled(int capacity, T fill) => + FixedSizeList(capacity, list: List.filled(capacity, fill)); + + factory FixedSizeList.empty(int capacity) => + FixedSizeList(capacity, list: List.empty()); + + factory FixedSizeList.from(Iterable elements) => + FixedSizeList(elements.length, list: List.from(elements)); + + factory FixedSizeList.of(Iterable elements) => + FixedSizeList(elements.length, list: List.of(elements)); + + factory FixedSizeList.generate(int length, T generator(int index)) => + FixedSizeList(length, list: List.generate(length, generator)); + /// Returns an unmodifiable view of the current items in the list. /// /// This prevents external modification of the internal list. List get items => List.unmodifiable(_list); + + // Delegate all other List methods to the internal list + @override + int get length => _list.length; + + @override + set length(int newLength) { + RangeError.checkValidRange(0, _capacity, newLength); + _list.length = newLength; + } + + @override + T operator [](int index) => _list[index]; + + @override + void operator []=(int index, T value) { + _list[index] = value; + } + + @override + void addAll(Iterable iterable) { + for (final T i in iterable) { + _list.add(i); + } + } + + @override + bool any(bool Function(T element) test) => _list.any(test); + + @override + Map asMap() => _list.asMap(); + + @override + List cast() => _list.cast(); + + @override + void clear() => _list.clear(); + + @override + bool contains(Object? element) => _list.contains(element); + + @override + T elementAt(int index) => _list.elementAt(index); + + @override + bool every(bool Function(T element) test) => _list.every(test); + + @override + Iterable expand(Iterable Function(T element) toElements) => + _list.expand(toElements); + + @override + T firstWhere(bool Function(T element) test, {T Function()? orElse}) => + _list.firstWhere(test, orElse: orElse); + + @override + E fold(E initialValue, E Function(E previousValue, T element) combine) => + _list.fold(initialValue, combine); + + @override + Iterable followedBy(Iterable other) => _list.followedBy(other); + + @override + void forEach(void Function(T element) action) => _list.forEach(action); + + @override + Iterable getRange(int start, int end) => _list.getRange(start, end); + + @override + int indexOf(T element, [int startIndex = 0]) => + _list.indexOf(element, startIndex); + + @override + int indexWhere(bool Function(T element) test, [int startIndex = 0]) => + _list.indexWhere(test, startIndex); + + @override + void insert(int index, T element) { + _list.insert(index, element); + if (_list.length > _capacity) { + _list.removeAt(0); + } + } + + @override + void insertAll(int index, Iterable iterable) { + _list.insertAll(index, iterable); + + while (_list.length > _capacity) { + _list.removeAt(0); + } + } + + @override + bool get isEmpty => _list.isEmpty; + + @override + bool get isNotEmpty => _list.isNotEmpty; + + @override + Iterator get iterator => _list.iterator; + + @override + String join([String separator = ""]) => _list.join(separator); + + @override + T lastWhere(bool Function(T element) test, {T Function()? orElse}) => + _list.lastWhere(test, orElse: orElse); + + @override + Iterable map(E Function(T e) toElement) => _list.map(toElement); + + @override + T reduce(T Function(T value, T element) combine) => _list.reduce(combine); + + @override + T removeAt(int index) => _list.removeAt(index); + + @override + bool remove(Object? value) => _list.remove(value); + + @override + void removeRange(int start, int end) => _list.removeRange(start, end); + + @override + void removeWhere(bool Function(T element) test) => _list.removeWhere(test); + + @override + void replaceRange(int start, int end, Iterable newContents) => + _list.replaceRange(start, end, newContents); + + @override + void retainWhere(bool Function(T element) test) => _list.retainWhere(test); + + @override + Iterable get reversed => _list.reversed; + + @override + void setAll(int index, Iterable iterable) => _list.setAll(index, iterable); + + @override + void setRange( + int start, + int end, + Iterable iterable, [ + int skipCount = 0, + ]) => + _list.setRange(start, end, iterable, skipCount); + + @override + T singleWhere(bool Function(T element) test, {T Function()? orElse}) => + _list.singleWhere(test, orElse: orElse); + + @override + Iterable skip(int count) => _list.skip(count); + + @override + Iterable skipWhile(bool Function(T value) test) => _list.skipWhile(test); + + @override + List sublist(int start, [int? end]) => _list.sublist(start, end); + + @override + Iterable take(int count) => _list.take(count); + + @override + Iterable takeWhile(bool Function(T value) test) => _list.takeWhile(test); + + @override + List toList({bool growable = true}) => _list.toList(growable: growable); + + @override + Set toSet() => _list.toSet(); + + @override + String toString() => _list.toString(); + + @override + void sort([Comparator? compare]) => _list.sort(compare); + + @override + void shuffle([Random? random]) => _list.shuffle(random); + + @override + T get first => _list.first; + + @override + T get last => _list.last; + + @override + T get single => _list.single; + + @override + List operator +(List other) => _list + other; + + @override + void fillRange(int start, int end, [T? fillValue]) => + _list.fillRange(start, end, fillValue); + + @override + set first(T value) => _list.first; + + @override + set last(T value) => _list.last; + + @override + int lastIndexOf(T element, [int? start]) => _list.lastIndexOf(element, start); + + @override + int lastIndexWhere(bool Function(T element) test, [int? start]) => + _list.lastIndexWhere(test as bool Function(T?), start); + + @override + T removeLast() => _list.removeLast(); + + @override + Iterable where(bool Function(T element) test) => + _list.where(test as bool Function(T?)).cast(); + + @override + Iterable whereType() => _list.whereType(); } diff --git a/pubspec.yaml b/pubspec.yaml index c986a83..3e95cca 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: arcane_helper_utils description: Provides a variety of helpful utilities and extensions for Flutter and Dart. -version: 1.4.3 +version: 1.4.4 repository: https://github.com/hanskokx/arcane_helper_utils issue_tracker: https://github.com/hanskokx/arcane_helper_utils/issues