Convert withModal to useModal

This commit is contained in:
Ken-Håvard Lieng 2020-05-03 09:05:16 +02:00
parent 9cf42df1ea
commit 530e08b9ee
32 changed files with 791 additions and 737 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
import React, { Suspense, lazy, useState } from 'react';
import React, { Suspense, lazy, useState, useEffect } from 'react';
import Route from 'containers/Route';
import AppInfo from 'components/AppInfo';
import TabList from 'components/TabList';
@ -28,6 +28,11 @@ const App = ({
setRenderModals(true);
}
const [starting, setStarting] = useState(true);
useEffect(() => {
setTimeout(() => setStarting(false), 1000);
}, []);
const mainClass = cn('main-container', {
'off-canvas': showTabList
});
@ -40,7 +45,7 @@ const App = ({
return (
<div className="wrap" onClick={handleClick}>
{!connected && (
{!starting && !connected && (
<AppInfo type="error">
Connection lost, attempting to reconnect...
</AppInfo>

View File

@ -61,7 +61,7 @@ export default class TabList extends PureComponent {
<div
key={`${address}-chans}`}
className="tab-label"
onClick={() => openModal('channel', { server: address })}
onClick={() => openModal('channel', address)}
>
<span>CHANNELS {chanLabel}</span>
<Button title="Join Channel">+</Button>

View File

@ -1,20 +1,23 @@
import React, { memo, useState, useEffect, useCallback, useRef } from 'react';
import get from 'lodash/get';
import React, { memo, useState, useEffect, useRef } from 'react';
import Modal from 'react-modal';
import { useSelector, useDispatch } from 'react-redux';
import { FiUsers, FiX } from 'react-icons/fi';
import withModal from 'components/modals/withModal';
import useModal from 'components/modals/useModal';
import Button from 'components/ui/Button';
import { join } from 'state/channels';
import { select } from 'state/tab';
import { searchChannels } from 'state/channelSearch';
import { linkify } from 'utils';
const Channel = memo(({ server, name, topic, userCount, joined, ...props }) => {
const handleJoinClick = useCallback(() => props.join([name], server), []);
const Channel = memo(({ server, name, topic, userCount, joined }) => {
const dispatch = useDispatch();
const handleClick = () => dispatch(join([name], server));
return (
<div className="modal-channel-result">
<div className="modal-channel-result-header">
<h2 className="modal-channel-name" onClick={handleJoinClick}>
<h2 className="modal-channel-name" onClick={handleClick}>
{name}
</h2>
<FiUsers />
@ -25,7 +28,7 @@ const Channel = memo(({ server, name, topic, userCount, joined, ...props }) => {
<Button
className="modal-channel-button-join"
category="normal"
onClick={handleJoinClick}
onClick={handleClick}
>
Join
</Button>
@ -36,7 +39,12 @@ const Channel = memo(({ server, name, topic, userCount, joined, ...props }) => {
);
});
const AddChannel = ({ search, payload: { server }, onClose, ...props }) => {
const AddChannel = () => {
const [modal, server, closeModal] = useModal('channel');
const channels = useSelector(state => state.channels);
const search = useSelector(state => state.channelSearch);
const dispatch = useDispatch();
const [q, setQ] = useState('');
const inputEl = useRef();
@ -44,12 +52,15 @@ const AddChannel = ({ search, payload: { server }, onClose, ...props }) => {
const prevSearch = useRef('');
useEffect(() => {
inputEl.current.focus();
props.searchChannels(server, '');
}, []);
if (modal.isOpen) {
dispatch(searchChannels(server, ''));
setTimeout(() => inputEl.current.focus(), 0);
} else {
setQ('');
}
}, [modal.isOpen]);
const handleSearch = useCallback(
e => {
const handleSearch = e => {
let nextQ = e.target.value.trim().toLowerCase();
setQ(nextQ);
@ -62,34 +73,30 @@ const AddChannel = ({ search, payload: { server }, onClose, ...props }) => {
if (nextQ !== prevSearch.current) {
prevSearch.current = nextQ;
props.searchChannels(server, nextQ);
dispatch(searchChannels(server, nextQ));
}
}
},
[q]
);
};
const handleKey = useCallback(e => {
const handleKey = e => {
if (e.key === 'Enter') {
let channel = e.target.value.trim();
if (channel !== '') {
onClose(false);
closeModal(false);
if (channel.charAt(0) !== '#') {
channel = `#${channel}`;
}
props.join([channel], server);
props.select(server, channel);
dispatch(join([channel], server));
dispatch(select(server, channel));
}
}
}, []);
};
const handleLoadMore = useCallback(
() => props.searchChannels(server, q, search.results.length),
[q, search.results.length]
);
const handleLoadMore = () =>
dispatch(searchChannels(server, q, search.results.length));
let hasMore = !search.end;
if (hasMore) {
@ -104,7 +111,7 @@ const AddChannel = ({ search, payload: { server }, onClose, ...props }) => {
}
return (
<>
<Modal {...modal}>
<div className="modal-channel-input-wrap">
<input
ref={inputEl}
@ -117,7 +124,7 @@ const AddChannel = ({ search, payload: { server }, onClose, ...props }) => {
<Button
icon={FiX}
className="modal-close modal-channel-close"
onClick={onClose}
onClick={closeModal}
/>
</div>
<div ref={resultsEl} className="modal-channel-results">
@ -125,12 +132,7 @@ const AddChannel = ({ search, payload: { server }, onClose, ...props }) => {
<Channel
key={`${server} ${channel.name}`}
server={server}
join={props.join}
joined={get(
props.channels,
[server, channel.name, 'joined'],
false
)}
joined={channels[server]?.[channel.name]?.joined}
{...channel}
/>
))}
@ -143,15 +145,8 @@ const AddChannel = ({ search, payload: { server }, onClose, ...props }) => {
</Button>
)}
</div>
</>
</Modal>
);
};
export default withModal({
name: 'channel',
state: {
channels: state => state.channels,
search: state => state.channelSearch
},
actions: { searchChannels, join, select }
})(AddChannel);
export default AddChannel;

View File

@ -1,27 +1,26 @@
import React, { useCallback } from 'react';
import withModal from 'components/modals/withModal';
import React from 'react';
import Modal from 'react-modal';
import useModal from 'components/modals/useModal';
import Button from 'components/ui/Button';
const Confirm = ({
payload: { question, confirmation, onConfirm },
onClose
}) => {
const handleConfirm = useCallback(() => {
onClose(false);
const Confirm = () => {
const [modal, payload, closeModal] = useModal('confirm');
const { question, confirmation, onConfirm } = payload;
const handleConfirm = () => {
closeModal(false);
onConfirm();
}, []);
};
return (
<>
<Modal {...modal}>
<p>{question}</p>
<Button onClick={handleConfirm}>{confirmation || 'OK'}</Button>
<Button category="normal" onClick={onClose}>
<Button category="normal" onClick={closeModal}>
Cancel
</Button>
</>
</Modal>
);
};
export default withModal({
name: 'confirm'
})(Confirm);
export default Confirm;

View File

@ -1,21 +1,26 @@
import React from 'react';
import Modal from 'react-modal';
import { useSelector } from 'react-redux';
import { FiX } from 'react-icons/fi';
import Button from 'components/ui/Button';
import withModal from 'components/modals/withModal';
import useModal from 'components/modals/useModal';
import { getSelectedChannel } from 'state/channels';
import { linkify } from 'utils';
const Topic = ({ payload: { topic, channel }, onClose }) => {
const Topic = () => {
const [modal, channel, closeModal] = useModal('topic');
const topic = useSelector(state => getSelectedChannel(state)?.topic);
return (
<>
<Modal {...modal}>
<div className="modal-header">
<h2>Topic in {channel}</h2>
<Button icon={FiX} className="modal-close" onClick={onClose} />
<Button icon={FiX} className="modal-close" onClick={closeModal} />
</div>
<p className="modal-content">{linkify(topic)}</p>
</>
</Modal>
);
};
export default withModal({
name: 'topic'
})(Topic);
export default Topic;

View File

@ -0,0 +1,46 @@
import { useCallback } from 'react';
import Modal from 'react-modal';
import { useSelector, useDispatch } from 'react-redux';
import { closeModal } from 'state/modals';
Modal.setAppElement('#root');
const defaultPayload = {};
export default function useModal(name) {
const isOpen = useSelector(state => state.modals[name]?.isOpen || false);
const payload = useSelector(
state => state.modals[name]?.payload || defaultPayload
);
const dispatch = useDispatch();
const handleRequestClose = useCallback(
(dismissed = true) => {
dispatch(closeModal(name));
if (dismissed && payload.onDismiss) {
payload.onDismiss();
}
},
[payload.onDismiss]
);
const modalProps = {
isOpen,
contentLabel: name,
onRequestClose: handleRequestClose,
className: {
base: `modal modal-${name}`,
afterOpen: 'modal-opening',
beforeClose: 'modal-closing'
},
overlayClassName: {
base: 'modal-overlay',
afterOpen: 'modal-overlay-opening',
beforeClose: 'modal-overlay-closing'
},
closeTimeoutMS: 200
};
return [modalProps, payload, handleRequestClose];
}

View File

@ -1,71 +0,0 @@
import React, { useCallback } from 'react';
import Modal from 'react-modal';
import { createStructuredSelector } from 'reselect';
import get from 'lodash/get';
import { getModals, closeModal } from 'state/modals';
import connect from 'utils/connect';
import { bindActionCreators } from 'redux';
Modal.setAppElement('#root');
export default function withModal({ name, ...modalProps }) {
modalProps = {
className: {
base: `modal modal-${name}`,
afterOpen: 'modal-opening',
beforeClose: 'modal-closing'
},
overlayClassName: {
base: 'modal-overlay',
afterOpen: 'modal-overlay-opening',
beforeClose: 'modal-overlay-closing'
},
closeTimeoutMS: 200,
...modalProps
};
return WrappedComponent => {
const ReduxModal = ({ onRequestClose, ...props }) => {
const handleRequestClose = useCallback(
(dismissed = true) => {
onRequestClose();
if (dismissed && props.payload.onDismiss) {
props.payload.onDismiss();
}
},
[props.payload.onDismiss]
);
return (
<Modal
contentLabel={name}
onRequestClose={handleRequestClose}
{...modalProps}
{...props}
>
<WrappedComponent onClose={handleRequestClose} {...props} />
</Modal>
);
};
const mapState = createStructuredSelector({
isOpen: state => get(getModals(state), [name, 'isOpen'], false),
payload: state => get(getModals(state), [name, 'payload'], {}),
...modalProps.state
});
const mapDispatch = dispatch => {
const actions = { onRequestClose: () => dispatch(closeModal(name)) };
if (modalProps.actions) {
return {
...actions,
...bindActionCreators(modalProps.actions, dispatch)
};
}
return actions;
};
return connect(mapState, mapDispatch)(ReduxModal);
};
}

View File

@ -50,12 +50,7 @@ const ChatTitle = ({
{channel && channel.topic && (
<span
className="chat-topic"
onClick={() =>
openModal('topic', {
topic: channel.topic,
channel: channel.name
})
}
onClick={() => openModal('topic', channel.name)}
>
{channel.topic}
</span>

View File

@ -1,5 +1,6 @@
import { socket as socketActions } from 'state/actions';
import { getWrapWidth, appSet } from 'state/app';
import { getConnected, getWrapWidth, appSet } from 'state/app';
import { searchChannels } from 'state/channelSearch';
import { addMessages } from 'state/messages';
import { setSettings } from 'state/settings';
import { when } from 'utils/observe';
@ -12,6 +13,13 @@ function loadState({ store }, env) {
type: socketActions.SERVERS,
data: env.servers
});
when(store, getConnected, () =>
// Cache top channels for each server
env.servers.forEach(({ host }) =>
store.dispatch(searchChannels(host, ''))
)
);
}
if (env.channels) {

View File

@ -9,7 +9,7 @@ export const getWindowWidth = state => state.app.windowWidth;
export const getConnectDefaults = state => state.app.connectDefaults;
const initialState = {
connected: true,
connected: false,
wrapWidth: 0,
charWidth: 0,
windowWidth: 0,

View File

@ -3,11 +3,12 @@ import * as actions from 'state/actions';
const initialState = {
results: [],
end: false
end: false,
topCache: {}
};
export default createReducer(initialState, {
[actions.socket.CHANNEL_SEARCH](state, { results, start }) {
[actions.socket.CHANNEL_SEARCH](state, { results, start, server, q }) {
if (results) {
state.end = false;
@ -15,15 +16,20 @@ export default createReducer(initialState, {
state.results.push(...results);
} else {
state.results = results;
if (!q) {
state.topCache[server] = results;
}
}
} else {
state.end = true;
}
},
[actions.OPEN_MODAL](state, { name }) {
[actions.OPEN_MODAL](state, { name, payload }) {
if (name === 'channel') {
return initialState;
state.results = state.topCache[payload] || [];
state.end = false;
}
}
});

2
go.mod
View File

@ -23,7 +23,7 @@ require (
github.com/jpillora/backoff v1.0.0
github.com/kjk/betterguid v0.0.0-20170621091430-c442874ba63a
github.com/klauspost/cpuid v1.2.3
github.com/mailru/easyjson v0.7.1
github.com/mailru/easyjson v0.7.2-0.20200424172602-f0a000e7a8e0
github.com/miekg/dns v1.1.29 // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/mapstructure v1.3.0 // indirect

4
go.sum
View File

@ -246,6 +246,8 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@ -287,6 +289,8 @@ github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzR
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.7.1 h1:mdxE1MF9o53iCb2Ghj1VfWvh7ZOwHpnVG/xwXrV90U8=
github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mailru/easyjson v0.7.2-0.20200424172602-f0a000e7a8e0 h1:kBQYXw1PdcnwYP5hntk8LEDPdq++fubPN76BlfGLdIM=
github.com/mailru/easyjson v0.7.2-0.20200424172602-f0a000e7a8e0/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=

View File

@ -30,7 +30,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchServer(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -46,7 +46,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchServer(in *jlexer.Lexer, out
if out.Defaults == nil {
out.Defaults = new(config.Defaults)
}
easyjson7e607aefDecodeGithubComKhliengDispatchConfig(in, &*out.Defaults)
easyjson7e607aefDecodeGithubComKhliengDispatchConfig(in, out.Defaults)
}
case "servers":
if in.IsNull() {
@ -56,7 +56,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchServer(in *jlexer.Lexer, out
in.Delim('[')
if out.Servers == nil {
if !in.IsDelim(']') {
out.Servers = make([]Server, 0, 1)
out.Servers = make([]Server, 0, 0)
} else {
out.Servers = []Server{}
}
@ -97,7 +97,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchServer(in *jlexer.Lexer, out
if v2 == nil {
v2 = new(storage.Channel)
}
easyjson7e607aefDecodeGithubComKhliengDispatchStorage(in, &*v2)
easyjson7e607aefDecodeGithubComKhliengDispatchStorage(in, v2)
}
out.Channels = append(out.Channels, v2)
in.WantComma()
@ -162,12 +162,8 @@ func easyjson7e607aefEncodeGithubComKhliengDispatchServer(out *jwriter.Writer, i
_ = first
if in.Defaults != nil {
const prefix string = ",\"defaults\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
easyjson7e607aefEncodeGithubComKhliengDispatchConfig(out, *in.Defaults)
}
if len(in.Servers) != 0 {
@ -299,7 +295,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchStorage(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -329,12 +325,8 @@ func easyjson7e607aefEncodeGithubComKhliengDispatchStorage(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Name != "" {
@ -370,7 +362,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchConfig(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -431,12 +423,8 @@ func easyjson7e607aefEncodeGithubComKhliengDispatchConfig(out *jwriter.Writer, i
_ = first
if in.Name != "" {
const prefix string = ",\"name\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Name))
}
if in.Host != "" {
@ -531,7 +519,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchServer1(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -561,12 +549,8 @@ func easyjson7e607aefEncodeGithubComKhliengDispatchServer1(out *jwriter.Writer,
_ = first
if in.Tag != "" {
const prefix string = ",\"tag\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Tag))
}
if in.Commit != "" {
@ -626,7 +610,7 @@ func easyjson7e607aefDecodeGithubComKhliengDispatchServer2(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -687,12 +671,8 @@ func easyjson7e607aefEncodeGithubComKhliengDispatchServer2(out *jwriter.Writer,
_ = first
if in.Name != "" {
const prefix string = ",\"name\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Name))
}
if in.Host != "" {

View File

@ -212,8 +212,8 @@ type ChannelSearch struct {
}
type ChannelSearchResult struct {
ChannelSearch
Results []*storage.ChannelListItem
Start int
}
type ChannelForward struct {

View File

@ -1,4 +1,4 @@
// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.
//out.Data: false//v7: false//v24: false// Code generated by easyjson for marshaling/unmarshaling. DO NOT EDIT.
package server
@ -29,7 +29,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -86,12 +86,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer(out *jwriter.Writer, i
_ = first
if in.Nick != "" {
const prefix string = ",\"nick\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Nick))
}
if in.Username != "" {
@ -190,7 +186,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer1(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -218,12 +214,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer1(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.User != "" {
@ -273,7 +265,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer2(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -307,12 +299,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer2(out *jwriter.Writer,
_ = first
if in.Type != "" {
const prefix string = ",\"type\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Type))
}
if in.Data != nil {
@ -368,7 +356,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer3(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -398,12 +386,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer3(out *jwriter.Writer,
_ = first
if in.Type != "" {
const prefix string = ",\"type\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Type))
}
if (in.Data).IsDefined() {
@ -453,7 +437,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer4(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -504,12 +488,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer4(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Channel != "" {
@ -578,7 +558,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer5(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -610,12 +590,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer5(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Channel != "" {
@ -685,7 +661,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer6(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -713,12 +689,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer6(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Name != "" {
@ -769,7 +741,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer7(in *jlexer.Lexer, out
out.Server = new(storage.Server)
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -839,12 +811,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer7(out *jwriter.Writer,
_ = first
if true {
const prefix string = ",\"status\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Raw((in.Status).MarshalJSON())
}
if len(in.Features) != 0 {
@ -994,7 +962,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer8(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -1014,7 +982,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer8(in *jlexer.Lexer, out
in.Delim('[')
if out.Results == nil {
if !in.IsDelim(']') {
out.Results = make([]storage.Message, 0, 1)
out.Results = make([]storage.Message, 0, 0)
} else {
out.Results = []storage.Message{}
}
@ -1045,12 +1013,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer8(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Channel != "" {
@ -1119,7 +1083,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchStorage(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -1190,7 +1154,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer9(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -1220,12 +1184,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer9(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Channel != "" {
@ -1285,7 +1245,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer10(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -1313,12 +1273,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer10(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.SkipVerify {
@ -1368,7 +1324,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer11(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -1396,12 +1352,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer11(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Message != "" {
@ -1451,7 +1403,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer12(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -1481,12 +1433,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer12(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.User != "" {
@ -1546,7 +1494,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer13(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -1601,12 +1549,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer13(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.User != "" {
@ -1695,7 +1639,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer14(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -1721,12 +1665,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer14(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
out.RawByte('}')
@ -1766,7 +1706,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer15(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -1796,12 +1736,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer15(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Old != "" {
@ -1861,7 +1797,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer16(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -1895,12 +1831,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer16(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Channel != "" {
@ -1980,7 +1912,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer17(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -2000,7 +1932,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer17(in *jlexer.Lexer, ou
in.Delim('[')
if out.Messages == nil {
if !in.IsDelim(']') {
out.Messages = make([]storage.Message, 0, 1)
out.Messages = make([]storage.Message, 0, 0)
} else {
out.Messages = []storage.Message{}
}
@ -2035,12 +1967,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer17(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.To != "" {
@ -2129,7 +2057,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer18(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -2165,12 +2093,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer18(out *jwriter.Writer,
_ = first
if in.ID != "" {
const prefix string = ",\"id\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.ID))
}
if in.Server != "" {
@ -2260,7 +2184,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer19(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -2311,12 +2235,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer19(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Title != "" {
@ -2385,7 +2305,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer20(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -2415,12 +2335,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer20(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Channel != "" {
@ -2480,7 +2396,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer21(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -2531,12 +2447,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer21(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.User != "" {
@ -2605,7 +2517,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer22(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -2635,12 +2547,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer22(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Channel != "" {
@ -2700,7 +2608,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer23(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -2730,12 +2638,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer23(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Target != "" {
@ -2795,7 +2699,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer24(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -2825,12 +2729,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer24(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Channel != "" {
@ -2890,7 +2790,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer25(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -2942,12 +2842,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer25(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if len(in.Features) != 0 {
@ -3017,7 +2913,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer26(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -3045,12 +2941,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer26(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Message != "" {
@ -3100,7 +2992,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer27(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -3132,12 +3024,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer27(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Connected {
@ -3207,7 +3095,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer28(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -3235,12 +3123,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer28(out *jwriter.Writer,
_ = first
if in.Cert != "" {
const prefix string = ",\"cert\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Cert))
}
if in.Key != "" {
@ -3290,7 +3174,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer29(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -3322,13 +3206,17 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer29(in *jlexer.Lexer, ou
if v26 == nil {
v26 = new(storage.ChannelListItem)
}
easyjson42239ddeDecodeGithubComKhliengDispatchStorage1(in, &*v26)
easyjson42239ddeDecodeGithubComKhliengDispatchStorage1(in, v26)
}
out.Results = append(out.Results, v26)
in.WantComma()
}
in.Delim(']')
}
case "server":
out.Server = string(in.String())
case "q":
out.Q = string(in.String())
case "start":
out.Start = int(in.Int())
default:
@ -3347,12 +3235,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer29(out *jwriter.Writer,
_ = first
if len(in.Results) != 0 {
const prefix string = ",\"results\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
{
out.RawByte('[')
for v27, v28 := range in.Results {
@ -3368,6 +3252,26 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer29(out *jwriter.Writer,
out.RawByte(']')
}
}
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Q != "" {
const prefix string = ",\"q\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Q))
}
if in.Start != 0 {
const prefix string = ",\"start\":"
if first {
@ -3415,7 +3319,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchStorage1(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -3445,12 +3349,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchStorage1(out *jwriter.Writer,
_ = first
if in.Name != "" {
const prefix string = ",\"name\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Name))
}
if in.UserCount != 0 {
@ -3486,7 +3386,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer30(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -3516,12 +3416,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer30(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Q != "" {
@ -3581,7 +3477,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer31(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -3611,12 +3507,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer31(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Old != "" {
@ -3676,7 +3568,7 @@ func easyjson42239ddeDecodeGithubComKhliengDispatchServer32(in *jlexer.Lexer, ou
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -3704,12 +3596,8 @@ func easyjson42239ddeEncodeGithubComKhliengDispatchServer32(out *jwriter.Writer,
_ = first
if in.Server != "" {
const prefix string = ",\"server\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.String(string(in.Server))
}
if in.Message != "" {

View File

@ -295,8 +295,8 @@ func (h *wsHandler) channelSearch(b []byte) {
}
h.state.sendJSON("channel_search", ChannelSearchResult{
ChannelSearch: data,
Results: index.SearchN(data.Q, data.Start, n),
Start: data.Start,
})
}

View File

@ -28,7 +28,7 @@ func easyjson9e1087fdDecodeGithubComKhliengDispatchStorage(in *jlexer.Lexer, out
}
in.Delim('{')
for !in.IsDelim('}') {
key := in.UnsafeString()
key := in.UnsafeFieldName(false)
in.WantColon()
if in.IsNull() {
in.Skip()
@ -54,12 +54,8 @@ func easyjson9e1087fdEncodeGithubComKhliengDispatchStorage(out *jwriter.Writer,
_ = first
if in.ColoredNicks {
const prefix string = ",\"coloredNicks\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Bool(bool(in.ColoredNicks))
}
out.RawByte('}')

5
vendor/github.com/josharian/intern/README.md generated vendored Normal file
View File

@ -0,0 +1,5 @@
Docs: https://godoc.org/github.com/josharian/intern
See also [Go issue 5160](https://golang.org/issue/5160).
License: MIT

3
vendor/github.com/josharian/intern/go.mod generated vendored Normal file
View File

@ -0,0 +1,3 @@
module github.com/josharian/intern
go 1.5

44
vendor/github.com/josharian/intern/intern.go generated vendored Normal file
View File

@ -0,0 +1,44 @@
// Package intern interns strings.
// Interning is best effort only.
// Interned strings may be removed automatically
// at any time without notification.
// All functions may be called concurrently
// with themselves and each other.
package intern
import "sync"
var (
pool sync.Pool = sync.Pool{
New: func() interface{} {
return make(map[string]string)
},
}
)
// String returns s, interned.
func String(s string) string {
m := pool.Get().(map[string]string)
c, ok := m[s]
if ok {
pool.Put(m)
return c
}
m[s] = s
pool.Put(m)
return s
}
// Bytes returns b converted to a string, interned.
func Bytes(b []byte) string {
m := pool.Get().(map[string]string)
c, ok := m[string(b)]
if ok {
pool.Put(m)
return c
}
s := string(b)
m[s] = s
pool.Put(m)
return s
}

21
vendor/github.com/josharian/intern/license.md generated vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Josh Bleecher Snyder
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -20,6 +20,12 @@ generate: build
./tests/reference_to_pointer.go \
./tests/html.go \
./tests/unknown_fields.go \
./tests/type_declaration.go \
./tests/members_escaped.go \
./tests/members_unescaped.go \
./tests/intern.go \
./tests/nocopy.go \
./tests/escaping.go \
bin/easyjson -all ./tests/data.go
bin/easyjson -all ./tests/nothing.go
@ -27,7 +33,7 @@ generate: build
bin/easyjson -all ./tests/html.go
bin/easyjson -snake_case ./tests/snake.go
bin/easyjson -omit_empty ./tests/omitempty.go
bin/easyjson -build_tags=use_easyjson ./benchmark/data.go
bin/easyjson -build_tags=use_easyjson -disable_members_unescape ./benchmark/data.go
bin/easyjson ./tests/nested_easy.go
bin/easyjson ./tests/named_type.go
bin/easyjson ./tests/custom_map_key_type.go
@ -36,6 +42,12 @@ generate: build
bin/easyjson ./tests/key_marshaler_map.go
bin/easyjson -disallow_unknown_fields ./tests/disallow_unknown.go
bin/easyjson ./tests/unknown_fields.go
bin/easyjson ./tests/type_declaration.go
bin/easyjson ./tests/members_escaped.go
bin/easyjson -disable_members_unescape ./tests/members_unescaped.go
bin/easyjson ./tests/intern.go
bin/easyjson ./tests/nocopy.go
bin/easyjson ./tests/escaping.go
test: generate
go test \

View File

@ -35,6 +35,8 @@ Usage of easyjson:
generate marshaler/unmarshalers for all structs in a file
-build_tags string
build tags to add to generated file
-byte
use simple bytes instead of Base64Bytes for slice of bytes
-leave_temps
do not delete temporary files
-no_std_marshalers
@ -55,6 +57,8 @@ Usage of easyjson:
only generate stubs for marshaler/unmarshaler funcs
-disallow_unknown_fields
return error if some unknown field in json appeared
-disable_members_unescape
disable unescaping of \uXXXX string sequences in member names
```
Using `-all` will generate marshalers/unmarshalers for all Go structs in the
@ -76,10 +80,22 @@ Additional option notes:
* `-build_tags` will add the specified build tags to generated Go sources.
## Structure json tag options
Besides standart json tag options like 'omitempty' the following are supported:
* 'nocopy' - disables allocation and copying of string values, making them
refer to original json buffer memory. This works great for short lived
objects which are not hold in memory after decoding and immediate usage.
Note if string requires unescaping it will be processed as normally.
* 'intern' - string "interning" (deduplication) to save memory when the very
same string dictionary values are often met all over the structure.
See below for more details.
## Generated Marshaler/Unmarshaler Funcs
For Go struct types, easyjson generates the funcs `MarshalEasyJSON` /
`UnmarshalEasyJSON` for marshaling/unmarshaling JSON. In turn, these satisify
`UnmarshalEasyJSON` for marshaling/unmarshaling JSON. In turn, these satisfy
the `easyjson.Marshaler` and `easyjson.Unmarshaler` interfaces and when used in
conjunction with `easyjson.Marshal` / `easyjson.Unmarshal` avoid unnecessary
reflection / type assertions during marshaling/unmarshaling to/from JSON for Go
@ -102,17 +118,17 @@ utility funcs that are available.
## Controlling easyjson Marshaling and Unmarshaling Behavior
Go types can provide their own `MarshalEasyJSON` and `UnmarshalEasyJSON` funcs
that satisify the `easyjson.Marshaler` / `easyjson.Unmarshaler` interfaces.
that satisfy the `easyjson.Marshaler` / `easyjson.Unmarshaler` interfaces.
These will be used by `easyjson.Marshal` and `easyjson.Unmarshal` when defined
for a Go type.
Go types can also satisify the `easyjson.Optional` interface, which allows the
Go types can also satisfy the `easyjson.Optional` interface, which allows the
type to define its own `omitempty` logic.
## Type Wrappers
easyjson provides additional type wrappers defined in the `easyjson/opt`
package. These wrap the standard Go primitives and in turn satisify the
package. These wrap the standard Go primitives and in turn satisfy the
easyjson interfaces.
The `easyjson/opt` type wrappers are useful when needing to distinguish between
@ -133,6 +149,27 @@ through a call to `buffer.Init()` prior to any marshaling or unmarshaling.
Please see the [GoDoc listing](https://godoc.org/github.com/mailru/easyjson/buffer)
for more information.
## String interning
During unmarshaling, `string` field values can be optionally
[interned](https://en.wikipedia.org/wiki/String_interning) to reduce memory
allocations and usage by deduplicating strings in memory, at the expense of slightly
increased CPU usage.
This will work effectively only for `string` fields being decoded that have frequently
the same value (e.g. if you have a string field that can only assume a small number
of possible values).
To enable string interning, add the `intern` keyword tag to your `json` tag on `string`
fields, e.g.:
```go
type Foo struct {
UUID string `json:"uuid"` // will not be interned during unmarshaling
State string `json:"state,intern"` // will be interned during unmarshaling
}
```
## Issues, Notes, and Limitations
* easyjson is still early in its development. As such, there are likely to be
@ -174,7 +211,7 @@ for more information.
needs to be known prior to sending the data. Currently this is not possible
with easyjson's architecture.
* easyjson parser and codegen based on reflection, so it wont works on `package main`
* easyjson parser and codegen based on reflection, so it won't work on `package main`
files, because they cant be imported by parser.
## Benchmarks
@ -239,7 +276,7 @@ since the memory is not freed between marshaling operations.
### easyjson vs 'ujson' python module
[ujson](https://github.com/esnme/ultrajson) is using C code for parsing, so it
is interesting to see how plain golang compares to that. It is imporant to note
is interesting to see how plain golang compares to that. It is important to note
that the resulting object for python is slower to access, since the library
parses JSON object into dictionaries.

View File

@ -4,6 +4,7 @@ package buffer
import (
"io"
"net"
"sync"
)
@ -52,16 +53,14 @@ func putBuf(buf []byte) {
// getBuf gets a chunk from reuse pool or creates a new one if reuse failed.
func getBuf(size int) []byte {
if size < config.PooledSize {
return make([]byte, 0, size)
}
if size >= config.PooledSize {
if c := buffers[size]; c != nil {
v := c.Get()
if v != nil {
return v.([]byte)
}
}
}
return make([]byte, 0, size)
}
@ -78,9 +77,12 @@ type Buffer struct {
// EnsureSpace makes sure that the current chunk contains at least s free bytes,
// possibly creating a new chunk.
func (b *Buffer) EnsureSpace(s int) {
if cap(b.Buf)-len(b.Buf) >= s {
return
if cap(b.Buf)-len(b.Buf) < s {
b.ensureSpaceSlow(s)
}
}
func (b *Buffer) ensureSpaceSlow(s int) {
l := len(b.Buf)
if l > 0 {
if cap(b.toPool) != cap(b.Buf) {
@ -105,18 +107,22 @@ func (b *Buffer) EnsureSpace(s int) {
// AppendByte appends a single byte to buffer.
func (b *Buffer) AppendByte(data byte) {
if cap(b.Buf) == len(b.Buf) { // EnsureSpace won't be inlined.
b.EnsureSpace(1)
}
b.Buf = append(b.Buf, data)
}
// AppendBytes appends a byte slice to buffer.
func (b *Buffer) AppendBytes(data []byte) {
for len(data) > 0 {
if cap(b.Buf) == len(b.Buf) { // EnsureSpace won't be inlined.
b.EnsureSpace(1)
if len(data) <= cap(b.Buf)-len(b.Buf) {
b.Buf = append(b.Buf, data...) // fast path
} else {
b.appendBytesSlow(data)
}
}
func (b *Buffer) appendBytesSlow(data []byte) {
for len(data) > 0 {
b.EnsureSpace(1)
sz := cap(b.Buf) - len(b.Buf)
if sz > len(data) {
@ -128,12 +134,18 @@ func (b *Buffer) AppendBytes(data []byte) {
}
}
// AppendBytes appends a string to buffer.
// AppendString appends a string to buffer.
func (b *Buffer) AppendString(data string) {
for len(data) > 0 {
if cap(b.Buf) == len(b.Buf) { // EnsureSpace won't be inlined.
b.EnsureSpace(1)
if len(data) <= cap(b.Buf)-len(b.Buf) {
b.Buf = append(b.Buf, data...) // fast path
} else {
b.appendStringSlow(data)
}
}
func (b *Buffer) appendStringSlow(data string) {
for len(data) > 0 {
b.EnsureSpace(1)
sz := cap(b.Buf) - len(b.Buf)
if sz > len(data) {
@ -156,18 +168,14 @@ func (b *Buffer) Size() int {
// DumpTo outputs the contents of a buffer to a writer and resets the buffer.
func (b *Buffer) DumpTo(w io.Writer) (written int, err error) {
var n int
for _, buf := range b.bufs {
if err == nil {
n, err = w.Write(buf)
written += n
}
putBuf(buf)
bufs := net.Buffers(b.bufs)
if len(b.Buf) > 0 {
bufs = append(bufs, b.Buf)
}
n, err := bufs.WriteTo(w)
if err == nil {
n, err = w.Write(b.Buf)
written += n
for _, buf := range b.bufs {
putBuf(buf)
}
putBuf(b.toPool)
@ -175,7 +183,7 @@ func (b *Buffer) DumpTo(w io.Writer) (written int, err error) {
b.Buf = nil
b.toPool = nil
return
return int(n), err
}
// BuildBytes creates a single byte slice with all the contents of the buffer. Data is
@ -192,7 +200,7 @@ func (b *Buffer) BuildBytes(reuse ...[]byte) []byte {
var ret []byte
size := b.Size()
// If we got a buffer as argument and it is big enought, reuse it.
// If we got a buffer as argument and it is big enough, reuse it.
if len(reuse) == 1 && cap(reuse[0]) >= size {
ret = reuse[0][:0]
} else {

View File

@ -1,3 +1,5 @@
module github.com/mailru/easyjson
go 1.12
require github.com/josharian/intern v1.0.0

View File

@ -6,6 +6,7 @@ import (
"io/ioutil"
"net/http"
"strconv"
"unsafe"
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
@ -36,9 +37,17 @@ type UnknownsMarshaler interface {
MarshalUnknowns(w *jwriter.Writer, first bool)
}
func isNilInterface(i interface{}) bool {
return (*[2]uintptr)(unsafe.Pointer(&i))[1] == 0
}
// Marshal returns data as a single byte slice. Method is suboptimal as the data is likely to be copied
// from a chain of smaller chunks.
func Marshal(v Marshaler) ([]byte, error) {
if isNilInterface(v) {
return nullBytes, nil
}
w := jwriter.Writer{}
v.MarshalEasyJSON(&w)
return w.BuildBytes()
@ -46,6 +55,10 @@ func Marshal(v Marshaler) ([]byte, error) {
// MarshalToWriter marshals the data to an io.Writer.
func MarshalToWriter(v Marshaler, w io.Writer) (written int, err error) {
if isNilInterface(v) {
return w.Write(nullBytes)
}
jw := jwriter.Writer{}
v.MarshalEasyJSON(&jw)
return jw.DumpTo(w)
@ -56,6 +69,13 @@ func MarshalToWriter(v Marshaler, w io.Writer) (written int, err error) {
// false if an error occurred before any http.ResponseWriter methods were actually
// invoked (in this case a 500 reply is possible).
func MarshalToHTTPResponseWriter(v Marshaler, w http.ResponseWriter) (started bool, written int, err error) {
if isNilInterface(v) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Content-Length", strconv.Itoa(len(nullBytes)))
written, err = w.Write(nullBytes)
return true, written, err
}
jw := jwriter.Writer{}
v.MarshalEasyJSON(&jw)
if jw.Error != nil {

View File

@ -5,6 +5,7 @@
package jlexer
import (
"bytes"
"encoding/base64"
"encoding/json"
"errors"
@ -14,6 +15,8 @@ import (
"unicode"
"unicode/utf16"
"unicode/utf8"
"github.com/josharian/intern"
)
// tokenKind determines type of a token.
@ -33,6 +36,7 @@ type token struct {
kind tokenKind // Type of a token.
boolValue bool // Value if a boolean literal token.
byteValueCloned bool // true if byteValue was allocated and does not refer to original json body
byteValue []byte // Raw value of a token.
delimValue byte
}
@ -240,23 +244,65 @@ func (r *Lexer) fetchNumber() {
// findStringLen tries to scan into the string literal for ending quote char to determine required size.
// The size will be exact if no escapes are present and may be inexact if there are escaped chars.
func findStringLen(data []byte) (isValid, hasEscapes bool, length int) {
delta := 0
for i := 0; i < len(data); i++ {
switch data[i] {
case '\\':
i++
delta++
if i < len(data) && data[i] == 'u' {
delta++
}
case '"':
return true, (delta > 0), (i - delta)
func findStringLen(data []byte) (isValid bool, length int) {
for {
idx := bytes.IndexByte(data, '"')
if idx == -1 {
return false, len(data)
}
if idx == 0 || (idx > 0 && data[idx-1] != '\\') {
return true, length + idx
}
return false, false, len(data)
// count \\\\\\\ sequences. even number of slashes means quote is not really escaped
cnt := 1
for idx-cnt-1 >= 0 && data[idx-cnt-1] == '\\' {
cnt++
}
if cnt%2 == 0 {
return true, length + idx
}
length += idx + 1
data = data[idx+1:]
}
}
// unescapeStringToken performs unescaping of string token.
// if no escaping is needed, original string is returned, otherwise - a new one allocated
func (r *Lexer) unescapeStringToken() (err error) {
data := r.token.byteValue
var unescapedData []byte
for {
i := bytes.IndexByte(data, '\\')
if i == -1 {
break
}
escapedRune, escapedBytes, err := decodeEscape(data[i:])
if err != nil {
r.errParse(err.Error())
return err
}
if unescapedData == nil {
unescapedData = make([]byte, 0, len(r.token.byteValue))
}
var d [4]byte
s := utf8.EncodeRune(d[:], escapedRune)
unescapedData = append(unescapedData, data[:i]...)
unescapedData = append(unescapedData, d[:s]...)
data = data[i+escapedBytes:]
}
if unescapedData != nil {
r.token.byteValue = append(unescapedData, data...)
r.token.byteValueCloned = true
}
return
}
// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
@ -286,36 +332,30 @@ func getu4(s []byte) rune {
return val
}
// processEscape processes a single escape sequence and returns number of bytes processed.
func (r *Lexer) processEscape(data []byte) (int, error) {
// decodeEscape processes a single escape sequence and returns number of bytes processed.
func decodeEscape(data []byte) (decoded rune, bytesProcessed int, err error) {
if len(data) < 2 {
return 0, fmt.Errorf("syntax error at %v", string(data))
return 0, 0, errors.New("incorrect escape symbol \\ at the end of token")
}
c := data[1]
switch c {
case '"', '/', '\\':
r.token.byteValue = append(r.token.byteValue, c)
return 2, nil
return rune(c), 2, nil
case 'b':
r.token.byteValue = append(r.token.byteValue, '\b')
return 2, nil
return '\b', 2, nil
case 'f':
r.token.byteValue = append(r.token.byteValue, '\f')
return 2, nil
return '\f', 2, nil
case 'n':
r.token.byteValue = append(r.token.byteValue, '\n')
return 2, nil
return '\n', 2, nil
case 'r':
r.token.byteValue = append(r.token.byteValue, '\r')
return 2, nil
return '\r', 2, nil
case 't':
r.token.byteValue = append(r.token.byteValue, '\t')
return 2, nil
return '\t', 2, nil
case 'u':
rr := getu4(data)
if rr < 0 {
return 0, errors.New("syntax error")
return 0, 0, errors.New("incorrectly escaped \\uXXXX sequence")
}
read := 6
@ -328,13 +368,10 @@ func (r *Lexer) processEscape(data []byte) (int, error) {
rr = unicode.ReplacementChar
}
}
var d [4]byte
s := utf8.EncodeRune(d[:], rr)
r.token.byteValue = append(r.token.byteValue, d[:s]...)
return read, nil
return rr, read, nil
}
return 0, errors.New("syntax error")
return 0, 0, errors.New("incorrectly escaped bytes")
}
// fetchString scans a string literal token.
@ -342,43 +379,14 @@ func (r *Lexer) fetchString() {
r.pos++
data := r.Data[r.pos:]
isValid, hasEscapes, length := findStringLen(data)
isValid, length := findStringLen(data)
if !isValid {
r.pos += length
r.errParse("unterminated string literal")
return
}
if !hasEscapes {
r.token.byteValue = data[:length]
r.pos += length + 1
return
}
r.token.byteValue = make([]byte, 0, length)
p := 0
for i := 0; i < len(data); {
switch data[i] {
case '"':
r.pos += i + 1
r.token.byteValue = append(r.token.byteValue, data[p:i]...)
i++
return
case '\\':
r.token.byteValue = append(r.token.byteValue, data[p:i]...)
off, err := r.processEscape(data[i:])
if err != nil {
r.errParse(err.Error())
return
}
i += off
p = i
default:
i++
}
}
r.errParse("unterminated string literal")
r.pos += length + 1 // skip closing '"' as well
}
// scanToken scans the next token if no token is currently available in the lexer.
@ -602,7 +610,7 @@ func (r *Lexer) Consumed() {
}
}
func (r *Lexer) unsafeString() (string, []byte) {
func (r *Lexer) unsafeString(skipUnescape bool) (string, []byte) {
if r.token.kind == tokenUndef && r.Ok() {
r.FetchToken()
}
@ -610,6 +618,13 @@ func (r *Lexer) unsafeString() (string, []byte) {
r.errInvalidToken("string")
return "", nil
}
if !skipUnescape {
if err := r.unescapeStringToken(); err != nil {
r.errInvalidToken("string")
return "", nil
}
}
bytes := r.token.byteValue
ret := bytesToStr(r.token.byteValue)
r.consume()
@ -621,13 +636,19 @@ func (r *Lexer) unsafeString() (string, []byte) {
// Warning: returned string may point to the input buffer, so the string should not outlive
// the input buffer. Intended pattern of usage is as an argument to a switch statement.
func (r *Lexer) UnsafeString() string {
ret, _ := r.unsafeString()
ret, _ := r.unsafeString(false)
return ret
}
// UnsafeBytes returns the byte slice if the token is a string literal.
func (r *Lexer) UnsafeBytes() []byte {
_, ret := r.unsafeString()
_, ret := r.unsafeString(false)
return ret
}
// UnsafeFieldName returns current member name string token
func (r *Lexer) UnsafeFieldName(skipUnescape bool) string {
ret, _ := r.unsafeString(skipUnescape)
return ret
}
@ -640,7 +661,34 @@ func (r *Lexer) String() string {
r.errInvalidToken("string")
return ""
}
ret := string(r.token.byteValue)
if err := r.unescapeStringToken(); err != nil {
r.errInvalidToken("string")
return ""
}
var ret string
if r.token.byteValueCloned {
ret = bytesToStr(r.token.byteValue)
} else {
ret = string(r.token.byteValue)
}
r.consume()
return ret
}
// StringIntern reads a string literal, and performs string interning on it.
func (r *Lexer) StringIntern() string {
if r.token.kind == tokenUndef && r.Ok() {
r.FetchToken()
}
if !r.Ok() || r.token.kind != tokenString {
r.errInvalidToken("string")
return ""
}
if err := r.unescapeStringToken(); err != nil {
r.errInvalidToken("string")
return ""
}
ret := intern.Bytes(r.token.byteValue)
r.consume()
return ret
}
@ -839,7 +887,7 @@ func (r *Lexer) Int() int {
}
func (r *Lexer) Uint8Str() uint8 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@ -856,7 +904,7 @@ func (r *Lexer) Uint8Str() uint8 {
}
func (r *Lexer) Uint16Str() uint16 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@ -873,7 +921,7 @@ func (r *Lexer) Uint16Str() uint16 {
}
func (r *Lexer) Uint32Str() uint32 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@ -890,7 +938,7 @@ func (r *Lexer) Uint32Str() uint32 {
}
func (r *Lexer) Uint64Str() uint64 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@ -915,7 +963,7 @@ func (r *Lexer) UintptrStr() uintptr {
}
func (r *Lexer) Int8Str() int8 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@ -932,7 +980,7 @@ func (r *Lexer) Int8Str() int8 {
}
func (r *Lexer) Int16Str() int16 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@ -949,7 +997,7 @@ func (r *Lexer) Int16Str() int16 {
}
func (r *Lexer) Int32Str() int32 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@ -966,7 +1014,7 @@ func (r *Lexer) Int32Str() int32 {
}
func (r *Lexer) Int64Str() int64 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@ -1004,7 +1052,7 @@ func (r *Lexer) Float32() float32 {
}
func (r *Lexer) Float32Str() float32 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}
@ -1037,7 +1085,7 @@ func (r *Lexer) Float64() float64 {
}
func (r *Lexer) Float64Str() float64 {
s, b := r.unsafeString()
s, b := r.unsafeString(false)
if !r.Ok() {
return 0
}

View File

@ -297,11 +297,9 @@ func (w *Writer) String(s string) {
p := 0 // last non-escape symbol
var escapeTable [128]bool
escapeTable := &htmlEscapeTable
if w.NoEscapeHTML {
escapeTable = htmlNoEscapeTable
} else {
escapeTable = htmlEscapeTable
escapeTable = &htmlNoEscapeTable
}
for i := 0; i < len(s); {

View File

@ -1,8 +1,6 @@
package easyjson
import (
json "encoding/json"
jlexer "github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
)
@ -10,14 +8,14 @@ import (
// UnknownFieldsProxy implemets UnknownsUnmarshaler and UnknownsMarshaler
// use it as embedded field in your structure to parse and then serialize unknown struct fields
type UnknownFieldsProxy struct {
unknownFields map[string]interface{}
unknownFields map[string][]byte
}
func (s *UnknownFieldsProxy) UnmarshalUnknown(in *jlexer.Lexer, key string) {
if s.unknownFields == nil {
s.unknownFields = make(map[string]interface{}, 1)
s.unknownFields = make(map[string][]byte, 1)
}
s.unknownFields[key] = in.Interface()
s.unknownFields[key] = in.Raw()
}
func (s UnknownFieldsProxy) MarshalUnknowns(out *jwriter.Writer, first bool) {
@ -29,6 +27,6 @@ func (s UnknownFieldsProxy) MarshalUnknowns(out *jwriter.Writer, first bool) {
}
out.String(string(key))
out.RawByte(':')
out.Raw(json.Marshal(val))
out.Raw(val, nil)
}
}

4
vendor/modules.txt vendored
View File

@ -130,6 +130,8 @@ github.com/hashicorp/hcl/json/token
github.com/inconshreveable/mousetrap
# github.com/jmhodges/levigo v1.0.0
## explicit
# github.com/josharian/intern v1.0.0
github.com/josharian/intern
# github.com/jpillora/backoff v1.0.0
## explicit
github.com/jpillora/backoff
@ -141,7 +143,7 @@ github.com/kjk/betterguid
github.com/klauspost/cpuid
# github.com/magiconair/properties v1.8.1
github.com/magiconair/properties
# github.com/mailru/easyjson v0.7.1
# github.com/mailru/easyjson v0.7.2-0.20200424172602-f0a000e7a8e0
## explicit
github.com/mailru/easyjson
github.com/mailru/easyjson/buffer