Skip to content

Commit e0d8464

Browse files
committed
Add file loading and serialization support
Features: - New pkg/persist package for file I/O and serialization - Support for canonical text format (default) - Efficient binary format for large rulesets - Comment filtering (#, //, ;) - LoadOptions for flexible loading (skip invalid, max rules, etc.) - Direct engine methods: LoadRulesFromFile, SaveRulesToFile - Export/Import methods for programmatic rule transfer Engine Integration: - LoadRulesFromFile() - Simple file loading - LoadRulesFromFileWithOptions() - Advanced options - SaveRulesToFile() - Save to canonical or binary format - ExportRules() / ImportRules() - Programmatic transfer - Full support for both Engine and AdaptiveEngine Binary Format: - Magic number: 'SPOCP' - Versioned format (v1) - Efficient for large rulesets - Automatic format detection Documentation: - Comprehensive FILE_LOADING.md guide - Working example in examples/fileio/ - Complete test coverage Tests: - 10 tests for persist package - 7 tests for engine integration - Benchmarks for format comparison - All tests passing
1 parent f5e205b commit e0d8464

File tree

8 files changed

+1916
-0
lines changed

8 files changed

+1916
-0
lines changed

adaptive_engine.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package spocp
22

33
import (
4+
"fmt"
5+
6+
"github.com/sirosfoundation/go-spocp/pkg/persist"
47
"github.com/sirosfoundation/go-spocp/pkg/sexp"
58
)
69

@@ -166,3 +169,49 @@ func (ae *AdaptiveEngine) ForceIndexing(enabled bool) {
166169
ae.engine.indexEnabled = enabled
167170
ae.stats.IndexingEnabled = enabled
168171
}
172+
173+
// LoadRulesFromFile loads rules from a file into the adaptive engine
174+
func (ae *AdaptiveEngine) LoadRulesFromFile(filename string) error {
175+
rules, err := persist.LoadFileToSlice(filename)
176+
if err != nil {
177+
return fmt.Errorf("failed to load rules: %w", err)
178+
}
179+
180+
for _, rule := range rules {
181+
ae.AddRuleElement(rule)
182+
}
183+
184+
return nil
185+
}
186+
187+
// LoadRulesFromFileWithOptions loads rules with custom options
188+
func (ae *AdaptiveEngine) LoadRulesFromFileWithOptions(filename string, opts persist.LoadOptions) error {
189+
rules, err := persist.LoadFile(filename, opts)
190+
if err != nil {
191+
return fmt.Errorf("failed to load rules: %w", err)
192+
}
193+
194+
for _, rule := range rules {
195+
ae.AddRuleElement(rule)
196+
}
197+
198+
return nil
199+
}
200+
201+
// SaveRulesToFile saves all rules from the engine to a file
202+
func (ae *AdaptiveEngine) SaveRulesToFile(filename string, format persist.FileFormat) error {
203+
return ae.engine.SaveRulesToFile(filename, format)
204+
}
205+
206+
// ExportRules returns all rules as a slice for serialization
207+
func (ae *AdaptiveEngine) ExportRules() []sexp.Element {
208+
return ae.engine.ExportRules()
209+
}
210+
211+
// ImportRules replaces all rules with the provided slice
212+
func (ae *AdaptiveEngine) ImportRules(rules []sexp.Element) {
213+
ae.Clear()
214+
for _, rule := range rules {
215+
ae.AddRuleElement(rule)
216+
}
217+
}

0 commit comments

Comments
 (0)