package plancontext import ( "fmt" "sync" "cuelang.org/go/cue" "go.dagger.io/dagger/compiler" "go.dagger.io/dagger/pkg" ) var ( serviceIDPath = cue.MakePath( cue.Str("$dagger"), cue.Str("service"), cue.Hid("_id", pkg.EnginePackage), ) ) func IsServiceValue(v *compiler.Value) bool { return v.LookupPath(serviceIDPath).Exists() } type Service struct { id string unix string npipe string } func (s *Service) ID() string { return s.id } func (s *Service) Unix() string { return s.unix } func (s *Service) NPipe() string { return s.npipe } func (s *Service) MarshalCUE() *compiler.Value { v := compiler.NewValue() if err := v.FillPath(serviceIDPath, s.id); err != nil { panic(err) } return v } type serviceContext struct { l sync.RWMutex store map[string]*Service } func (c *serviceContext) New(unix, npipe string) *Service { c.l.Lock() defer c.l.Unlock() s := &Service{ id: hashID(unix, npipe), unix: unix, npipe: npipe, } c.store[s.id] = s return s } func (c *serviceContext) FromValue(v *compiler.Value) (*Service, error) { c.l.RLock() defer c.l.RUnlock() if !v.LookupPath(serviceIDPath).IsConcrete() { return nil, fmt.Errorf("invalid service at path %q: service is not set", v.Path()) } id, err := v.LookupPath(serviceIDPath).String() if err != nil { return nil, fmt.Errorf("invalid service at path %q: %w", v.Path(), err) } s, ok := c.store[id] if !ok { return nil, fmt.Errorf("service %q not found", id) } return s, nil } func (c *serviceContext) Get(id string) *Service { c.l.RLock() defer c.l.RUnlock() return c.store[id] }