/* * Copyright 2023 jacqueline * * SPDX-License-Identifier: GPL-3.0-only */ #pragma once #include #include #include #include #include #include "bloom_filter.hpp" #include "database.hpp" #include "future_fetcher.hpp" #include "random.hpp" #include "track.hpp" namespace playlist { /* * Stateful interface for iterating over a collection of tracks by id. */ class ISource { public: virtual ~ISource() {} virtual auto Current() -> std::optional = 0; /* * Discards the current track id and continues to the next in this source. * Returns the new current track id. */ virtual auto Advance() -> std::optional = 0; /* * Repeatedly advances until a track with the given id is the current track. * Returns false if this source ran out of tracks before the requested id * was encounted, true otherwise. */ virtual auto AdvanceTo(database::TrackId id) -> bool { for (auto t = Current(); t.has_value(); t = Advance()) { if (*t == id) { return true; } } return false; } /* * Places the next n tracks into the given vector, in order. Does not change * the value returned by Current(). */ virtual auto Peek(std::size_t n, std::vector*) -> std::size_t = 0; }; /* * A Source that supports restarting iteration from its original initial * value. */ class IResetableSource : public ISource { public: virtual ~IResetableSource() {} virtual auto Previous() -> std::optional = 0; /* * Restarts iteration from this source's initial value. */ virtual auto Reset() -> void = 0; }; auto CreateSourceFromResults( std::weak_ptr, std::shared_ptr>) -> std::shared_ptr; class IndexRecordSource : public IResetableSource { public: IndexRecordSource(std::weak_ptr db, std::shared_ptr>); IndexRecordSource(std::weak_ptr db, std::shared_ptr>, std::size_t, std::shared_ptr>, std::size_t); auto Current() -> std::optional override; auto Advance() -> std::optional override; auto Peek(std::size_t n, std::vector*) -> std::size_t override; auto Previous() -> std::optional override; auto Reset() -> void override; private: std::weak_ptr db_; std::shared_ptr> initial_page_; ssize_t initial_item_; std::shared_ptr> current_page_; ssize_t current_item_; }; class NestedSource : public IResetableSource { public: NestedSource(std::weak_ptr db, std::shared_ptr>); auto Current() -> std::optional override; auto Advance() -> std::optional override; auto Peek(std::size_t n, std::vector*) -> std::size_t override; auto Previous() -> std::optional override; auto Reset() -> void override; private: auto CreateChild(std::shared_ptr page) -> std::shared_ptr; std::weak_ptr db_; std::shared_ptr> initial_page_; ssize_t initial_item_; std::shared_ptr> current_page_; ssize_t current_item_; std::shared_ptr current_child_; }; } // namespace playlist