PPysolate SpineREAD THE CODE · UNDERSTAND THE SYSTEM
章节目录
源码索引 / CURRENT IMPLEMENTATION

prefix.go

72 行 · 构建时读取的实际文件,不是讲解用伪代码。

package spine

import (
	"context"
	"errors"
	"fmt"

	"github.com/tetratelabs/wazero/api"
)

// RunPrefix receives append-only UTF-8 source fragments. Closing chunks commits
// the source for one execution in the same Guest; ctx cancels an unfinished stream.
func (r *Runner) RunPrefix(ctx context.Context, chunks <-chan string, inputs any) (Output, error) {
	if chunks == nil {
		return Output{}, errors.New("nil source stream")
	}
	for _, name := range []string{"prefix_begin", "prefix_feed"} {
		if r.code.ExportedFunctions()[name] == nil {
			return Output{}, fmt.Errorf("missing prefix Guest export: %s", name)
		}
	}
	return r.run(ctx, "", inputs, true, chunks)
}

func receiveSource(ctx context.Context, m api.Module, initial []byte, chunks <-chan string) error {
	status, err := callWithBytes(ctx, m, "prefix_begin", initial)
	if err != nil {
		return err
	}
	if status[0] != 0 {
		return errors.New("prefix initialization failed: ")
	}
	received := len(initial)
	for {
		select {
		case <-ctx.Done():
			return ctx.Err()
		case chunk, ok := <-chunks:
			if !ok {
				return ctx.Err()
			}
			received += len(chunk)
			if received > maxMessage {
				return errors.New("prefix input exceeds 1 MiB")
			}
			if chunk == "" {
				continue
			}
			status, err = callWithBytes(ctx, m, "prefix_feed", []byte(chunk))
			if err != nil {
				return err
			}
			if status[0] != 0 {
				return errors.New("prefix feed failed: ")
			}
		}
	}
}

// Request memory is temporary for this call; returned Guest response memory, if any,
// is owned by its caller. Shared by execute and the two prefix setup calls.
func callWithBytes(ctx context.Context, m api.Module, name string, data []byte) ([]uint64, error) {
	ptr, err := m.ExportedFunction("alloc").Call(ctx, uint64(len(data)))
	if err != nil {
		return nil, err
	}
	if ptr[0] == 0 || !m.Memory().Write(uint32(ptr[0]), data) {
		return nil, errors.New("Guest request allocation failed")
	}
	defer m.ExportedFunction("release").Call(ctx, ptr[0])
	return m.ExportedFunction(name).Call(ctx, ptr[0], uint64(len(data)))
}