about summary refs log tree commit diff
path: root/assets/src/network/channel/messages/event_handler.ts
diff options
context:
space:
mode:
Diffstat (limited to 'assets/src/network/channel/messages/event_handler.ts')
-rw-r--r--assets/src/network/channel/messages/event_handler.ts166
1 files changed, 0 insertions, 166 deletions
diff --git a/assets/src/network/channel/messages/event_handler.ts b/assets/src/network/channel/messages/event_handler.ts
deleted file mode 100644
index d0936e0..0000000
--- a/assets/src/network/channel/messages/event_handler.ts
+++ /dev/null
@@ -1,166 +0,0 @@
-import type { Channel } from "phoenix";
-import type {
-    AnyMessage,
-    EventName,
-    MessageForEvent,
-    TokenizedMessage,
-} from "./messages";
-
-// The single handler for all events, which is used to dispatch to the correct
-// handler for each event and token.
-// Every event can only have either one single handler, or multiple handlers for different tokens.
-export type EventHandler = {
-    [EN in EventName]?: HandlerForMessage<MessageForEvent<EN>>;
-};
-
-// A handler for a specific event and message.
-// A message handler can either be a single handler or can have multiple handlers for different tokens
-type HandlerForMessage<M extends AnyMessage> =
-    // A single handler
-    | { type: "single"; handler: HandlerFn<M> }
-    // A group of handlers for different tokens
-    // Can only be used for messages which have a "token" field.
-    | (M extends TokenizedMessage
-          ? {
-                type: "token";
-                handler: HandlerForTokenizedMessage<M>;
-            }
-          : never);
-
-// A map of token to handler for a specific event.
-export type HandlerForTokenizedMessage<M extends TokenizedMessage> = Map<
-    string,
-    HandlerFn<M>
->;
-
-// A function which handles a message for a specific event.
-export type HandlerFn<M extends AnyMessage> = (message?: M) => void;
-
-// A function that unregisters a single event handler.
-export type UnregisterFn = () => void;
-
-// Adds a single handler for a specific event.
-export function registerHandler<M extends AnyMessage>(
-    eventHandler: EventHandler,
-    channel: Channel,
-    event: M["event_name"],
-    handler: HandlerFn<M>
-) {
-    const messageHandler: HandlerForMessage<M> = {
-        type: "single",
-        handler,
-    };
-
-    let unregisterChannelEvent: UnregisterFn | null = null;
-    if (typeof eventHandler[event] === "undefined") {
-        // Register a new event handler, since this is the first handler for this event
-        unregisterChannelEvent = registerNewEvent<M>(
-            channel,
-            messageHandler,
-            event
-        );
-    } else {
-        throw new Error("Event already has a handler attached to it.");
-    }
-
-    // TODO: Check if we there is a possibility for TS to accept this.
-    // Technically this should work, because TS is afraid of the generic type parameter
-    // not matching the message type of the handler. But it should match, since
-    // the handler should accept only the exact message type from which the event_name was derived.
-    // @ts-ignore
-    eventHandler[event] = messageHandler;
-
-    // This could cause problems if we would allow to redefine the handler,
-    // as that would cause the Unsubscribe function to no longer apply to this specific handler,
-    // but as we throw an error on redefinition, this should be fine.
-    return () => {
-        delete eventHandler[event];
-
-        // If we registered a new event on the channel, we need to unregister it
-        if (unregisterChannelEvent !== null) {
-            unregisterChannelEvent();
-        }
-    };
-}
-
-export function registerHandlerForSpecificToken<M extends TokenizedMessage>(
-    eventHandler: EventHandler,
-    channel: Channel,
-    event: M["event_name"],
-    token: string,
-    handler: HandlerFn<M>
-): UnregisterFn {
-    const messageHandler = eventHandler[event];
-
-    if (typeof messageHandler === "undefined") {
-        // TODO: Same as above, this should probably be valid.
-        // @ts-ignore
-        eventHandler[event] = {
-            type: "token",
-            handler: new Map<string, HandlerFn<M>>(),
-        };
-        // @ts-ignore
-        registerNewEvent<M>(channel, eventHandler[event], event);
-    } else if (
-        messageHandler.type === "token" &&
-        messageHandler.handler.size === 0
-    ) {
-        // If there is already a token handler with no token, we need to register the event again
-        // @ts-ignore
-        registerNewEvent<M>(channel, messageHandler, event);
-    } else if (messageHandler.type === "single") {
-        throw new Error("Event already has a handler attached to it.");
-    }
-
-    // @ts-ignore This shoudl be valid, as we derive the event name from the message type.
-    const tokenHandler: HandlerForTokenizedMessage<M> =
-        eventHandler[event].handler;
-    tokenHandler.set(token, handler);
-
-    return () => {
-        // Unregister the handler for this specific token
-        tokenHandler.delete(token);
-        // If there are no more handlers for this event, we can unregister the event
-        if (tokenHandler.size === 0) {
-            // We should technically use the ref here, but we don't yet have a way to get it, as the event
-            // could have been registered outside of this function call.
-            channel.off(event);
-        }
-    };
-}
-
-// Adds a callback for a new event
-function registerNewEvent<M extends AnyMessage>(
-    channel: Channel,
-    messageHandler: HandlerForMessage<M>,
-    event: M["event_name"]
-): UnregisterFn {
-    const callback = (data: M) => {
-        // Add event_name to message, so the type definitions match
-        const message = { event_name: event, ...data };
-        onEvent<M>(messageHandler, message);
-    };
-
-    const ref = channel.on(event, callback);
-
-    return () => channel.off(event, ref);
-}
-
-function onEvent<M extends AnyMessage>(
-    messageHandler: HandlerForMessage<M>,
-    message: M
-) {
-    if (messageHandler.type === "token") {
-        const token: string = message["token"];
-
-        const handler = messageHandler.handler.get(token);
-
-        if (typeof handler !== "undefined") {
-            (handler as HandlerFn<M>)(message);
-        } else {
-            console.warn(`Received message for unknown token: ${token}`);
-        }
-    } else {
-        messageHandler.handler(message);
-    }
-}
lass="o">*Compiler { return &Compiler{ src: *source.NewWalker(src), codePos: 0, labelPositions: map[string]int{}, labelReferences: []labelReference{}, } } func (cpl *Compiler) Compile() (code.Code, error) { res := []byte{} for { _, eof, err := cpl.src.Peek() if err != nil { return code.Code{}, err } if eof { break } line, err := cpl.compileLine() if err != nil { return code.Code{}, err } cpl.codePos += len(line) res = append(res, line...) } if err := cpl.linkLabels(res); err != nil { return code.Code{}, err } return code.New(res), nil } func (cpl *Compiler) compileLine() ([]byte, error) { res := []byte{} start, value, err := cpl.splitLine() if err != nil || start == "" { return nil, err } // Ignore lines starting with a comment. if start[0] == '#' { return nil, nil } // Save the position of the label. if start[0] == '@' { label := strings.Trim(start, "@:") if _, ok := cpl.labelPositions[label]; ok { return nil, ErrDuplicateLabel{label} } cpl.labelPositions[label] = cpl.codePos return nil, nil } // Find the operator. op, err := cpl.compileOp(start) if err != nil { return nil, err } res = append(res, byte(op)) // Find the value, of which there is at most one. if value != "" { val, err := cpl.compileValue(value) if err != nil { return nil, err } res = append(res, val...) } return res, nil } func (cpl *Compiler) compileOp(str string) (code.Op, error) { op, err := StringToOp(str) if err != nil { return 0, err } return op, nil } func (cpl *Compiler) compileValue(str string) ([]byte, error) { res := make([]byte, 8) // Save label reference. if str[0] == '@' { label := strings.Trim(str, "@:") cpl.labelReferences = append(cpl.labelReferences, labelReference{ label: label, at: cpl.codePos + 1, // +1 to skip the opcode. }) return res, nil } if unicode.IsDigit(rune(str[0])) || str[0] == '-' { if strings.Contains(str, ".") { val, err := strconv.ParseFloat(str, 64) if err != nil { return res, err } binary.LittleEndian.PutUint64(res, math.Float64bits(val)) } else { val, err := strconv.ParseInt(str, 10, 64) if err != nil { return res, err } binary.LittleEndian.PutUint64(res, uint64(val)) } return res, nil } if str[0] == '"' { str = strings.Trim(str, "\"") res = []byte(str) res = append(res, 0) return res, nil } return res, ErrInvalidValue{str} } func (cpl *Compiler) splitLine() (string, string, error) { line := "" for { c, eof, err := cpl.src.Next() if err != nil { return "", "", err } if eof || c == '\n' { break } line += string(c) } fields := strings.Fields(line) if len(fields) == 0 { return "", "", nil } start := fields[0] if len(fields) > 1 { return start, strings.Join(fields[1:], " "), nil } return start, "", nil } type labelReference struct { label string at int } func (cpl *Compiler) linkLabels(code []byte) error { for _, ref := range cpl.labelReferences { pos, ok := cpl.labelPositions[ref.label] if !ok { return ErrUnkonwnLabel{ref.label} } binary.LittleEndian.PutUint64(code[ref.at:], uint64(pos)) } return nil }