Rune Caster 1.0.0
Modern C++ Text Processing Framework
Loading...
Searching...
No Matches
spell_composition.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "spell_base.hpp"
4#include <string>
5#include <utility>
6#include "rune_sequence.hpp"
7
8namespace rune_caster {
9
10namespace spell {
11namespace composition {
12
22template<typename FirstSpell, typename SecondSpell>
24 static_assert(spell_concept<FirstSpell>, "FirstSpell must satisfy spell_concept");
25 static_assert(spell_concept<SecondSpell>, "SecondSpell must satisfy spell_concept");
26 static_assert(chainable_spells<FirstSpell, SecondSpell>, "Spells must be chainable");
27
28private:
29 FirstSpell first_spell_;
30 SecondSpell second_spell_;
31 std::string description_;
32
33public:
34 using input_type = typename FirstSpell::input_type;
35 using output_type = typename SecondSpell::output_type;
36
42 constexpr SpellComposition(FirstSpell first, SecondSpell second)
43 : first_spell_(std::move(first))
44 , second_spell_(std::move(second))
45 , description_(first_spell_.description() + " → " + second_spell_.description())
46 {
47 static_assert(std::same_as<typename FirstSpell::output_type, typename SecondSpell::input_type>,
48 "Output type of first spell must match input type of second spell");
49 }
50
56 output_type operator()(const input_type& input) const override {
57 auto intermediate = first_spell_(input);
58 return second_spell_(intermediate);
59 }
60
61 std::string description() const override {
62 return description_;
63 }
64
65 std::string name() const override {
66 return first_spell_.name() + "→" + second_spell_.name();
67 }
68
72 const FirstSpell& first_spell() const noexcept { return first_spell_; }
73
77 const SecondSpell& second_spell() const noexcept { return second_spell_; }
78};
79
93template<typename FirstSpell, typename SecondSpell>
94auto compose(FirstSpell&& first, SecondSpell&& second) {
95 static_assert(spell_concept<FirstSpell>, "FirstSpell must satisfy spell_concept");
96 static_assert(spell_concept<SecondSpell>, "SecondSpell must satisfy spell_concept");
97 static_assert(chainable_spells<FirstSpell, SecondSpell>, "Spells must be chainable");
98
99 return SpellComposition<std::decay_t<FirstSpell>, std::decay_t<SecondSpell>>{
100 std::forward<FirstSpell>(first),
101 std::forward<SecondSpell>(second)
102 };
103}
104
116template<typename Spell>
118 static_assert(spell_for<Spell, RuneSequence>, "Spell must accept RuneSequence as input");
119 return spell(input);
120}
121
133template<typename Spell>
134std::string cast_spell(std::string_view utf8_input, const Spell& spell) {
135 static_assert(spell_for<Spell, RuneSequence>, "Spell must accept RuneSequence as input");
136 static_assert(std::same_as<typename Spell::output_type, RuneSequence>,
137 "Spell must output RuneSequence for string conversion");
138
139 auto sequence = RuneSequence::from_utf8(utf8_input);
140 auto result = spell(sequence);
141 return result.to_utf8();
142}
143
144} // namespace composition
145
146// Import composition utilities into the main spell namespace for convenience
147using composition::SpellComposition;
150
151} // namespace spell
152} // namespace rune_caster
static RuneString from_utf8(std::string_view utf8_text)
Create a RuneString from UTF-8 text.
Unified spell object for text transformation.
Composition of two spells into a single spell pipeline.
std::string description() const override
Get the spell's description.
const SecondSpell & second_spell() const noexcept
Get the second spell in the composition.
std::string name() const override
Get the spell's name.
constexpr SpellComposition(FirstSpell first, SecondSpell second)
Construct a spell composition.
output_type operator()(const input_type &input) const override
Apply the composed spells.
const FirstSpell & first_spell() const noexcept
Get the first spell in the composition.
Concept for spells that can be chained together.
Concept defining what makes a valid spell.
Concept for spells that work with specific input types.
RuneSequence cast_spell(const RuneSequence &input, const Spell &spell)
Helper function for casting spells on RuneSequence.
auto compose(FirstSpell &&first, SecondSpell &&second)
Compose two spells into a single spell pipeline.
RuneString RuneSequence
Backward compatibility alias for RuneString.
spell_base< RuneSequence > sequence_spell
Most common spell type: RuneSequence -> RuneSequence.