github.com/mutagen-io/mutagen@v0.18.0-rc1/pkg/service/prompting/stream.go (about) 1 package prompting 2 3 import ( 4 "errors" 5 "fmt" 6 ) 7 8 // streamPrompter implements Prompter on top of a Prompting_HostServer stream. 9 type streamPrompter struct { 10 // allowPrompts indicates whether or not the client allows prompts. 11 allowPrompts bool 12 // stream is the underlying Prompting_HostServer stream. 13 stream Prompting_HostServer 14 // errored indicates whether or not the stream has encountered an error. 15 errored bool 16 } 17 18 // sendReceive performs a send/receive cycle by sending a HostResponse and 19 // receiving a HostRequest. 20 func (p *streamPrompter) sendReceive(response *HostResponse) (*HostRequest, error) { 21 // Send the request. 22 if err := p.stream.Send(response); err != nil { 23 return nil, fmt.Errorf("unable to send response: %w", err) 24 } 25 26 // Determine the expected request mode. 27 mode := hostRequestModeMessageResponse 28 if response.IsPrompt { 29 mode = hostRequestModePromptResponse 30 } 31 32 // Receive the response. 33 if request, err := p.stream.Recv(); err != nil { 34 return nil, fmt.Errorf("unable to receive request: %w", err) 35 } else if err = request.ensureValid(mode); err != nil { 36 return nil, fmt.Errorf("invalid request received: %w", err) 37 } else { 38 return request, nil 39 } 40 } 41 42 // Message implements the Message method of Prompter. 43 func (p *streamPrompter) Message(message string) error { 44 // Check if a previous transmission error has occurred. 45 if p.errored { 46 return errors.New("prompter encountered previous error") 47 } 48 49 // Otherwise perform the messaging operation. 50 if _, err := p.sendReceive(&HostResponse{Message: message}); err != nil { 51 p.errored = true 52 return err 53 } 54 55 // Success. 56 return nil 57 } 58 59 // Prompt implements the Prompt method of Prompter. 60 func (p *streamPrompter) Prompt(prompt string) (string, error) { 61 // Check if a previous transmission error has occurred. 62 if p.errored { 63 return "", errors.New("prompter encountered previous error") 64 } 65 66 // Check whether or not prompts are supported by this client. 67 if !p.allowPrompts { 68 return "", errors.New("prompter only supports messaging") 69 } 70 71 // Perform the exchange. 72 response, err := p.sendReceive(&HostResponse{IsPrompt: true, Message: prompt}) 73 if err != nil { 74 p.errored = true 75 return "", err 76 } 77 78 // Success. 79 return response.Response, nil 80 }