Compare commits
	
		
			2 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| bf6077fc0c | |||
| 9a77a7bbc3 | 
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							@ -1,6 +1,6 @@
 | 
				
			|||||||
module git.tordarus.net/niri-tools/niri
 | 
					module git.tordarus.net/niri-tools/niri
 | 
				
			||||||
 | 
					
 | 
				
			||||||
go 1.24.4
 | 
					go 1.25
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	git.tordarus.net/tordarus/channel v0.1.20
 | 
						git.tordarus.net/tordarus/channel v0.1.20
 | 
				
			||||||
 | 
				
			|||||||
@ -26,6 +26,10 @@ func ActionSpawn(command []string) Action {
 | 
				
			|||||||
	return ActionCustom("Spawn", map[string]any{"command": command})
 | 
						return ActionCustom("Spawn", map[string]any{"command": command})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ActionSpawnSh(command string) Action {
 | 
				
			||||||
 | 
						return ActionCustom("SpawnSh", map[string]any{"command": command})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ActionDoScreenTransition(delay Option[time.Duration]) Action {
 | 
					func ActionDoScreenTransition(delay Option[time.Duration]) Action {
 | 
				
			||||||
	return ActionCustom("DoScreenTransition", map[string]any{"delay_ms": mapOption(delay, time.Duration.Milliseconds)})
 | 
						return ActionCustom("DoScreenTransition", map[string]any{"delay_ms": mapOption(delay, time.Duration.Milliseconds)})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -266,12 +270,12 @@ func ActionFocusWorkspacePrevious() Action {
 | 
				
			|||||||
	return ActionCustom("FocusWorkspacePrevious", map[string]any{})
 | 
						return ActionCustom("FocusWorkspacePrevious", map[string]any{})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ActionMoveWindowToWorkspaceDown() Action {
 | 
					func ActionMoveWindowToWorkspaceDown(focus bool) Action {
 | 
				
			||||||
	return ActionCustom("MoveWindowToWorkspaceDown", map[string]any{})
 | 
						return ActionCustom("MoveWindowToWorkspaceDown", map[string]any{"focus": focus})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ActionMoveWindowToWorkspaceUp() Action {
 | 
					func ActionMoveWindowToWorkspaceUp(focus bool) Action {
 | 
				
			||||||
	return ActionCustom("MoveWindowToWorkspaceUp", map[string]any{})
 | 
						return ActionCustom("MoveWindowToWorkspaceUp", map[string]any{"focus": focus})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ActionMoveWindowToWorkspace(id Option[WindowID], reference WorkspaceReferenceArg, focus bool) Action {
 | 
					func ActionMoveWindowToWorkspace(id Option[WindowID], reference WorkspaceReferenceArg, focus bool) Action {
 | 
				
			||||||
@ -335,7 +339,7 @@ func ActionFocusMonitorNext() Action {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ActionFocusMonitor(output OutputName) Action {
 | 
					func ActionFocusMonitor(output OutputName) Action {
 | 
				
			||||||
	return ActionCustom("FocusMonitorNext", map[string]any{"output": output})
 | 
						return ActionCustom("FocusMonitor", map[string]any{"output": output})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ActionMoveWindowToMonitorLeft() Action {
 | 
					func ActionMoveWindowToMonitorLeft() Action {
 | 
				
			||||||
@ -410,14 +414,26 @@ func ActionSwitchPresetColumnWidth() Action {
 | 
				
			|||||||
	return ActionCustom("SwitchPresetColumnWidth", map[string]any{})
 | 
						return ActionCustom("SwitchPresetColumnWidth", map[string]any{})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ActionSwitchPresetColumnWidthBack() Action {
 | 
				
			||||||
 | 
						return ActionCustom("SwitchPresetColumnWidthBack", map[string]any{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ActionSwitchPresetWindowWidth(id Option[WindowID]) Action {
 | 
					func ActionSwitchPresetWindowWidth(id Option[WindowID]) Action {
 | 
				
			||||||
	return ActionCustom("SwitchPresetWindowWidth", map[string]any{"id": id})
 | 
						return ActionCustom("SwitchPresetWindowWidth", map[string]any{"id": id})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ActionSwitchPresetWindowWidthBack(id Option[WindowID]) Action {
 | 
				
			||||||
 | 
						return ActionCustom("SwitchPresetWindowWidthBack", map[string]any{"id": id})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ActionSwitchPresetWindowHeight(id Option[WindowID]) Action {
 | 
					func ActionSwitchPresetWindowHeight(id Option[WindowID]) Action {
 | 
				
			||||||
	return ActionCustom("SwitchPresetWindowHeight", map[string]any{"id": id})
 | 
						return ActionCustom("SwitchPresetWindowHeight", map[string]any{"id": id})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ActionSwitchPresetWindowHeightBack(id Option[WindowID]) Action {
 | 
				
			||||||
 | 
						return ActionCustom("SwitchPresetWindowHeightBack", map[string]any{"id": id})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ActionMaximizeColumn() Action {
 | 
					func ActionMaximizeColumn() Action {
 | 
				
			||||||
	return ActionCustom("MaximizeColumn", map[string]any{})
 | 
						return ActionCustom("MaximizeColumn", map[string]any{})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -545,3 +561,7 @@ func ActionSetWindowUrgent(id Option[WindowID]) Action {
 | 
				
			|||||||
func ActionUnsetWindowUrgent(id Option[WindowID]) Action {
 | 
					func ActionUnsetWindowUrgent(id Option[WindowID]) Action {
 | 
				
			||||||
	return ActionCustom("UnsetWindowUrgent", map[string]any{"id": id})
 | 
						return ActionCustom("UnsetWindowUrgent", map[string]any{"id": id})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ActionLoadConfigFile() Action {
 | 
				
			||||||
 | 
						return ActionCustom("LoadConfigFile", map[string]any{})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -7,18 +7,25 @@ type Event interface {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type eventContainer struct {
 | 
					type eventContainer struct {
 | 
				
			||||||
	EventWorkspacesChanged            *EventWorkspacesChanged            `json:"WorkspacesChanged"`
 | 
						EventWorkspacesChanged            *EventWorkspacesChanged            `json:"WorkspacesChanged,omitempty"`
 | 
				
			||||||
	EventWorkspaceUrgencyChanged      *EventWorkspaceUrgencyChanged      `json:"WorkspaceUrgencyChanged"`
 | 
						EventWorkspaceUrgencyChanged      *EventWorkspaceUrgencyChanged      `json:"WorkspaceUrgencyChanged,omitempty"`
 | 
				
			||||||
	EventWorkspaceActivated           *EventWorkspaceActivated           `json:"WorkspaceActivated"`
 | 
						EventWorkspaceActivated           *EventWorkspaceActivated           `json:"WorkspaceActivated,omitempty"`
 | 
				
			||||||
	EventWorkspaceActiveWindowChanged *EventWorkspaceActiveWindowChanged `json:"WorkspaceActiveWindowChanged"`
 | 
						EventWorkspaceActiveWindowChanged *EventWorkspaceActiveWindowChanged `json:"WorkspaceActiveWindowChanged,omitempty"`
 | 
				
			||||||
	EventWindowsChanged               *EventWindowsChanged               `json:"WindowsChanged"`
 | 
						EventWindowsChanged               *EventWindowsChanged               `json:"WindowsChanged,omitempty"`
 | 
				
			||||||
	EventWindowOpenedOrChanged        *EventWindowOpenedOrChanged        `json:"WindowOpenedOrChanged"`
 | 
						EventWindowOpenedOrChanged        *EventWindowOpenedOrChanged        `json:"WindowOpenedOrChanged,omitempty"`
 | 
				
			||||||
	EventWindowClosed                 *EventWindowClosed                 `json:"WindowClosed"`
 | 
						EventWindowClosed                 *EventWindowClosed                 `json:"WindowClosed,omitempty"`
 | 
				
			||||||
	EventWindowFocusChanged           *EventWindowFocusChanged           `json:"WindowFocusChanged"`
 | 
						EventWindowFocusChanged           *EventWindowFocusChanged           `json:"WindowFocusChanged,omitempty"`
 | 
				
			||||||
	EventWindowUrgencyChanged         *EventWindowUrgencyChanged         `json:"WindowUrgencyChanged"`
 | 
						EventWindowUrgencyChanged         *EventWindowUrgencyChanged         `json:"WindowUrgencyChanged,omitempty"`
 | 
				
			||||||
	EventKeyboardLayoutsChanged       *EventKeyboardLayoutsChanged       `json:"KeyboardLayoutsChanged"`
 | 
						EventWindowLayoutsChanged         *EventWindowLayoutsChanged         `json:"WindowLayoutsChanged,omitempty"`
 | 
				
			||||||
	EventKeyboardLayoutSwitched       *EventKeyboardLayoutSwitched       `json:"KeyboardLayoutSwitched"`
 | 
						EventKeyboardLayoutsChanged       *EventKeyboardLayoutsChanged       `json:"KeyboardLayoutsChanged,omitempty"`
 | 
				
			||||||
	EventOverviewOpenedOrClosed       *EventOverviewOpenedOrClosed       `json:"OverviewOpenedOrClosed"`
 | 
						EventKeyboardLayoutSwitched       *EventKeyboardLayoutSwitched       `json:"KeyboardLayoutSwitched,omitempty"`
 | 
				
			||||||
 | 
						EventOverviewOpenedOrClosed       *EventOverviewOpenedOrClosed       `json:"OverviewOpenedOrClosed,omitempty"`
 | 
				
			||||||
 | 
						EventConfigLoaded                 *EventConfigLoaded                 `json:"ConfigLoaded,omitempty"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *eventContainer) String() string {
 | 
				
			||||||
 | 
						data, _ := json.Marshal(m)
 | 
				
			||||||
 | 
						return string(data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *eventContainer) event() Event {
 | 
					func (c *eventContainer) event() Event {
 | 
				
			||||||
@ -40,12 +47,16 @@ func (c *eventContainer) event() Event {
 | 
				
			|||||||
		return c.EventWindowFocusChanged
 | 
							return c.EventWindowFocusChanged
 | 
				
			||||||
	} else if c.EventWindowUrgencyChanged != nil {
 | 
						} else if c.EventWindowUrgencyChanged != nil {
 | 
				
			||||||
		return c.EventWindowUrgencyChanged
 | 
							return c.EventWindowUrgencyChanged
 | 
				
			||||||
 | 
						} else if c.EventWindowLayoutsChanged != nil {
 | 
				
			||||||
 | 
							return c.EventWindowLayoutsChanged
 | 
				
			||||||
	} else if c.EventKeyboardLayoutsChanged != nil {
 | 
						} else if c.EventKeyboardLayoutsChanged != nil {
 | 
				
			||||||
		return c.EventKeyboardLayoutsChanged
 | 
							return c.EventKeyboardLayoutsChanged
 | 
				
			||||||
	} else if c.EventKeyboardLayoutSwitched != nil {
 | 
						} else if c.EventKeyboardLayoutSwitched != nil {
 | 
				
			||||||
		return c.EventKeyboardLayoutSwitched
 | 
							return c.EventKeyboardLayoutSwitched
 | 
				
			||||||
	} else if c.EventOverviewOpenedOrClosed != nil {
 | 
						} else if c.EventOverviewOpenedOrClosed != nil {
 | 
				
			||||||
		return c.EventOverviewOpenedOrClosed
 | 
							return c.EventOverviewOpenedOrClosed
 | 
				
			||||||
 | 
						} else if c.EventConfigLoaded != nil {
 | 
				
			||||||
 | 
							return c.EventConfigLoaded
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &EventInvalid{}
 | 
						return &EventInvalid{}
 | 
				
			||||||
@ -164,6 +175,17 @@ func (m *EventWindowUrgencyChanged) String() string {
 | 
				
			|||||||
	return string(data)
 | 
						return string(data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type EventWindowLayoutsChanged struct {
 | 
				
			||||||
 | 
						Changes []WindowLayoutChange `json:"changes"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *EventWindowLayoutsChanged) private() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *EventWindowLayoutsChanged) String() string {
 | 
				
			||||||
 | 
						data, _ := json.Marshal(m)
 | 
				
			||||||
 | 
						return string(data)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type EventKeyboardLayoutsChanged struct {
 | 
					type EventKeyboardLayoutsChanged struct {
 | 
				
			||||||
	KeyboardLayouts KeyboardLayouts `json:"keyboard_layouts"`
 | 
						KeyboardLayouts KeyboardLayouts `json:"keyboard_layouts"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -196,3 +218,14 @@ func (m *EventOverviewOpenedOrClosed) String() string {
 | 
				
			|||||||
	data, _ := json.Marshal(m)
 | 
						data, _ := json.Marshal(m)
 | 
				
			||||||
	return string(data)
 | 
						return string(data)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type EventConfigLoaded struct {
 | 
				
			||||||
 | 
						Failed bool `json:"failed"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *EventConfigLoaded) private() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *EventConfigLoaded) String() string {
 | 
				
			||||||
 | 
						data, _ := json.Marshal(m)
 | 
				
			||||||
 | 
						return string(data)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -5,14 +5,15 @@ import "encoding/json"
 | 
				
			|||||||
type WindowID int
 | 
					type WindowID int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Window struct {
 | 
					type Window struct {
 | 
				
			||||||
	ID          WindowID    `json:"id"`
 | 
						ID          WindowID     `json:"id"`
 | 
				
			||||||
	Title       string      `json:"title"`
 | 
						Title       string       `json:"title"`
 | 
				
			||||||
	AppID       string      `json:"app_id"`
 | 
						AppID       string       `json:"app_id"`
 | 
				
			||||||
	PID         int         `json:"pid"`
 | 
						PID         int          `json:"pid"`
 | 
				
			||||||
	WorkspaceID WorkspaceID `json:"workspace_id"`
 | 
						WorkspaceID WorkspaceID  `json:"workspace_id"`
 | 
				
			||||||
	Urgent      bool        `json:"is_urgent"`
 | 
						Urgent      bool         `json:"is_urgent"`
 | 
				
			||||||
	Floating    bool        `json:"is_floating"`
 | 
						Floating    bool         `json:"is_floating"`
 | 
				
			||||||
	Focused     bool        `json:"is_focused"`
 | 
						Focused     bool         `json:"is_focused"`
 | 
				
			||||||
 | 
						Layout      WindowLayout `json:"layout"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m Window) String() string {
 | 
					func (m Window) String() string {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										16
									
								
								model_window_layout.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								model_window_layout.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					package niri
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "encoding/json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type WindowLayout struct {
 | 
				
			||||||
 | 
						PosInScrollingLayout   Option[[2]int]     `json:"pos_in_scrolling_layout"`
 | 
				
			||||||
 | 
						TileSize               [2]float64         `json:"tile_size"`
 | 
				
			||||||
 | 
						WindowSize             [2]int             `json:"window_size"`
 | 
				
			||||||
 | 
						TilePosInWorkspaceView Option[[2]float64] `json:"tile_pos_in_workspace_view"`
 | 
				
			||||||
 | 
						WindowOffsetInTile     [2]float64         `json:"window_offset_in_tile"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m WindowLayout) String() string {
 | 
				
			||||||
 | 
						data, _ := json.MarshalIndent(m, "", "\t")
 | 
				
			||||||
 | 
						return string(data)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										36
									
								
								model_window_layout_change.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								model_window_layout_change.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					package niri
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type WindowLayoutChange struct {
 | 
				
			||||||
 | 
						WindowID     WindowID
 | 
				
			||||||
 | 
						WindowLayout WindowLayout
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *WindowLayoutChange) UnmarshalJSON(data []byte) error {
 | 
				
			||||||
 | 
						arr := []any{}
 | 
				
			||||||
 | 
						if err := json.Unmarshal(data, &arr); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(arr) != 2 {
 | 
				
			||||||
 | 
							return fmt.Errorf("expected array of length 2 but got array of length %d", len(arr))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if wid, ok := arr[0].(float64); !ok {
 | 
				
			||||||
 | 
							return fmt.Errorf("expected array element at index 0 to be of type int")
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							m.WindowID = WindowID(wid)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if windowLayout, err := reencodeJson[WindowLayout](arr[1]); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("expected array element at index 1 to be of type WindowLayout")
 | 
				
			||||||
 | 
						} else if windowLayout != nil {
 | 
				
			||||||
 | 
							m.WindowLayout = *windowLayout
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								utils.go
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								utils.go
									
									
									
									
									
								
							@ -1,6 +1,7 @@
 | 
				
			|||||||
package niri
 | 
					package niri
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"bufio"
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
@ -8,6 +9,7 @@ import (
 | 
				
			|||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func notNull(c *Client) bool {
 | 
					func notNull(c *Client) bool {
 | 
				
			||||||
@ -85,6 +87,8 @@ func readSocketGeneric[T any](ctx context.Context, socket string, body io.Reader
 | 
				
			|||||||
				if errors.Is(err, io.EOF) {
 | 
									if errors.Is(err, io.EOF) {
 | 
				
			||||||
					return
 | 
										return
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
 | 
										// JSON parsing errors
 | 
				
			||||||
 | 
										//fmt.Println(err)
 | 
				
			||||||
					continue
 | 
										continue
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -113,3 +117,31 @@ func asJsonReader(v any) io.Reader {
 | 
				
			|||||||
	data, _ := json.Marshal(v)
 | 
						data, _ := json.Marshal(v)
 | 
				
			||||||
	return bytes.NewReader(append(data, '\n'))
 | 
						return bytes.NewReader(append(data, '\n'))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func reencodeJson[T any](data any) (*T, error) {
 | 
				
			||||||
 | 
						r, w := io.Pipe()
 | 
				
			||||||
 | 
						defer w.Close()
 | 
				
			||||||
 | 
						defer r.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wbuf := bufio.NewWriter(w)
 | 
				
			||||||
 | 
						rbuf := bufio.NewReader(r)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wg := &sync.WaitGroup{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						value := new(T)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var encErr error
 | 
				
			||||||
 | 
						wg.Go(func() { encErr = json.NewEncoder(wbuf).Encode(data); wbuf.Flush() })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var decErr error
 | 
				
			||||||
 | 
						wg.Go(func() { decErr = json.NewDecoder(rbuf).Decode(value) })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wg.Wait()
 | 
				
			||||||
 | 
						if encErr != nil {
 | 
				
			||||||
 | 
							return nil, encErr
 | 
				
			||||||
 | 
						} else if decErr != nil {
 | 
				
			||||||
 | 
							return nil, decErr
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return value, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user