mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 10:03:42 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			77 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			77 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package set
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"encoding/gob"
 | 
						|
	"fmt"
 | 
						|
)
 | 
						|
 | 
						|
// GobEncode is an implementation of the interface gob.GobEncoder, allowing
 | 
						|
// sets to be included in structures encoded via gob.
 | 
						|
//
 | 
						|
// The set rules are included in the serialized value, so the caller must
 | 
						|
// register its concrete rules type with gob.Register before using a
 | 
						|
// set in a gob, and possibly also implement GobEncode/GobDecode to customize
 | 
						|
// how any parameters are persisted.
 | 
						|
//
 | 
						|
// The set elements are also included, so if they are of non-primitive types
 | 
						|
// they too must be registered with gob.
 | 
						|
//
 | 
						|
// If the produced gob values will persist for a long time, the caller must
 | 
						|
// ensure compatibility of the rules implementation. In particular, if the
 | 
						|
// definition of element equivalence changes between encoding and decoding
 | 
						|
// then two distinct stored elements may be considered equivalent on decoding,
 | 
						|
// causing the recovered set to have fewer elements than when it was stored.
 | 
						|
func (s Set) GobEncode() ([]byte, error) {
 | 
						|
	gs := gobSet{
 | 
						|
		Version: 0,
 | 
						|
		Rules:   s.rules,
 | 
						|
		Values:  s.Values(),
 | 
						|
	}
 | 
						|
 | 
						|
	buf := &bytes.Buffer{}
 | 
						|
	enc := gob.NewEncoder(buf)
 | 
						|
	err := enc.Encode(gs)
 | 
						|
	if err != nil {
 | 
						|
		return nil, fmt.Errorf("error encoding set.Set: %s", err)
 | 
						|
	}
 | 
						|
 | 
						|
	return buf.Bytes(), nil
 | 
						|
}
 | 
						|
 | 
						|
// GobDecode is the opposite of GobEncode. See GobEncode for information
 | 
						|
// on the requirements for and caveats of including set values in gobs.
 | 
						|
func (s *Set) GobDecode(buf []byte) error {
 | 
						|
	r := bytes.NewReader(buf)
 | 
						|
	dec := gob.NewDecoder(r)
 | 
						|
 | 
						|
	var gs gobSet
 | 
						|
	err := dec.Decode(&gs)
 | 
						|
	if err != nil {
 | 
						|
		return fmt.Errorf("error decoding set.Set: %s", err)
 | 
						|
	}
 | 
						|
	if gs.Version != 0 {
 | 
						|
		return fmt.Errorf("unsupported set.Set encoding version %d; need 0", gs.Version)
 | 
						|
	}
 | 
						|
 | 
						|
	victim := NewSetFromSlice(gs.Rules, gs.Values)
 | 
						|
	s.vals = victim.vals
 | 
						|
	s.rules = victim.rules
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
type gobSet struct {
 | 
						|
	Version int
 | 
						|
	Rules   Rules
 | 
						|
 | 
						|
	// The bucket-based representation is for efficient in-memory access, but
 | 
						|
	// for serialization it's enough to just retain the values themselves,
 | 
						|
	// which we can re-bucket using the rules (which may have changed!) when
 | 
						|
	// we re-inflate.
 | 
						|
	Values []interface{}
 | 
						|
}
 | 
						|
 | 
						|
func init() {
 | 
						|
	gob.Register([]interface{}(nil))
 | 
						|
}
 |