зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to mozilla-central a=merge
This commit is contained in:
Коммит
044707fc78
|
@ -172,7 +172,7 @@ name = "bindgen"
|
|||
version = "0.37.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -280,10 +280,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.2.0"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1489,11 +1489,6 @@ name = "nodrop"
|
|||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "1.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "3.2.1"
|
||||
|
@ -2860,7 +2855,7 @@ dependencies = [
|
|||
"checksum bzip2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3eafc42c44e0d827de6b1c131175098fe7fb53b8ce8a47e65cb3ea94688be24"
|
||||
"checksum bzip2-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2c5162604199bbb17690ede847eaa6120a3f33d5ab4dcc8e7c25b16d849ae79b"
|
||||
"checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275"
|
||||
"checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
|
||||
"checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c"
|
||||
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
|
||||
"checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00"
|
||||
"checksum clang-sys 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7f7c04e52c35222fffcc3a115b5daf5f7e2bfb71c13c4e2321afe1fc71859c2"
|
||||
|
@ -2969,7 +2964,6 @@ dependencies = [
|
|||
"checksum new-ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8ccbebba6fb53a6d2bdcfaf79cb339bc136dee3bfff54dc337a334bafe36476a"
|
||||
"checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
|
||||
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
|
||||
"checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
|
||||
"checksum nom 3.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b"
|
||||
"checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525"
|
||||
"checksum num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0d2c31b75c36a993d30c7a13d70513cb93f02acafdd5b7ba250f9b0e18615de7"
|
||||
|
|
|
@ -137,6 +137,10 @@ PaymentUIService.prototype = {
|
|||
dialog.paymentDialogWrapper.updateRequest();
|
||||
},
|
||||
|
||||
closePayment(requestId) {
|
||||
this.closeDialog(requestId);
|
||||
},
|
||||
|
||||
// other helper methods
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,22 +1,12 @@
|
|||
#!/bin/bash
|
||||
|
||||
binutils_version=2.28.1
|
||||
make_flags='-j12'
|
||||
make_flags="-j$(nproc)"
|
||||
|
||||
root_dir="$1"
|
||||
if [ -z "$root_dir" -o ! -d "$root_dir" ]; then
|
||||
root_dir=$(mktemp -d)
|
||||
fi
|
||||
|
||||
cd $root_dir
|
||||
|
||||
if test -z $TMPDIR; then
|
||||
TMPDIR=/tmp/
|
||||
fi
|
||||
|
||||
# Download the source of the specified version of binutils
|
||||
wget -c --progress=dot:mega -P $TMPDIR ftp://ftp.gnu.org/gnu/binutils/binutils-${binutils_version}.tar.xz || exit 1
|
||||
tar xJf $TMPDIR/binutils-${binutils_version}.tar.xz
|
||||
|
||||
# Build binutils
|
||||
mkdir binutils-objdir
|
||||
cd binutils-objdir
|
||||
|
|
|
@ -7,10 +7,10 @@ export CC="$topsrcdir/clang/bin/clang -fgnu89-inline"
|
|||
export CXX="$topsrcdir/clang/bin/clang++"
|
||||
export LLVM_SYMBOLIZER="$topsrcdir/clang/bin/llvm-symbolizer"
|
||||
|
||||
# Use a newer binutils, from the tooltool gcc package, if it's there
|
||||
if [ -e "$topsrcdir/gcc/bin/ld" ]; then
|
||||
export CC="$CC -B $topsrcdir/gcc/bin"
|
||||
export CXX="$CXX -B $topsrcdir/gcc/bin"
|
||||
# Use a newer binutils, if it's there
|
||||
if [ -e "$topsrcdir/binutils/bin/ld" ]; then
|
||||
export CC="$CC -B $topsrcdir/binutils/bin"
|
||||
export CXX="$CXX -B $topsrcdir/binutils/bin"
|
||||
fi
|
||||
|
||||
# Enable ASan specific code and build workarounds
|
||||
|
|
|
@ -10,14 +10,16 @@ TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
|
|||
if [ -n "$FORCE_GCC" -o -n "$MOZ_PGO" ]; then
|
||||
CC="$TOOLTOOL_DIR/gcc/bin/gcc"
|
||||
CXX="$TOOLTOOL_DIR/gcc/bin/g++"
|
||||
|
||||
# We want to make sure we use binutils and other binaries in the tooltool
|
||||
# package.
|
||||
mk_add_options "export PATH=$TOOLTOOL_DIR/gcc/bin:$PATH"
|
||||
else
|
||||
CC="$TOOLTOOL_DIR/clang/bin/clang"
|
||||
CXX="$TOOLTOOL_DIR/clang/bin/clang++"
|
||||
export ENABLE_CLANG_PLUGIN=1
|
||||
|
||||
mk_add_options "export PATH=$TOOLTOOL_DIR/binutils/bin:$PATH"
|
||||
fi
|
||||
|
||||
# We want to make sure we use binutils and other binaries in the tooltool
|
||||
# package.
|
||||
mk_add_options "export PATH=$TOOLTOOL_DIR/gcc/bin:$PATH"
|
||||
|
||||
. "$topsrcdir/build/unix/mozconfig.stdcxx"
|
||||
|
|
|
@ -10,10 +10,10 @@ export RANLIB="$topsrcdir/clang/bin/llvm-ranlib"
|
|||
export CC="$topsrcdir/clang/bin/clang"
|
||||
export CXX="$topsrcdir/clang/bin/clang++"
|
||||
|
||||
# Use a newer binutils, from the tooltool gcc package, if it's there
|
||||
if [ -e "$topsrcdir/gcc/bin/ld" ]; then
|
||||
export CC="$CC -B $topsrcdir/gcc/bin"
|
||||
export CXX="$CXX -B $topsrcdir/gcc/bin"
|
||||
# Use a newer binutils, if it's there
|
||||
if [ -e "$topsrcdir/binutils/bin/ld" ]; then
|
||||
export CC="$CC -B $topsrcdir/binutils/bin"
|
||||
export CXX="$CXX -B $topsrcdir/binutils/bin"
|
||||
fi
|
||||
|
||||
ac_add_options --enable-lto
|
||||
|
|
|
@ -13,7 +13,7 @@ if [ -f "$TOOLTOOL_DIR/gcc/lib64/libstdc++.so" ]; then
|
|||
# We also put both possible 32-bits library paths.
|
||||
LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOOLTOOL_DIR/gcc/lib64:$TOOLTOOL_DIR/gcc/lib32:$TOOLTOOL_DIR/gcc/lib
|
||||
elif [ -f "$TOOLTOOL_DIR/clang/lib/libstdc++.so" ]; then
|
||||
LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOOLTOOL_DIR/clang/lib
|
||||
LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}$TOOLTOOL_DIR/clang/lib:$TOOLTOOL_DIR/clang/lib32
|
||||
fi
|
||||
|
||||
mk_add_options "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
|
||||
|
|
|
@ -7,10 +7,10 @@ export CC="$topsrcdir/clang/bin/clang"
|
|||
export CXX="$topsrcdir/clang/bin/clang++"
|
||||
export LLVM_SYMBOLIZER="$topsrcdir/clang/bin/llvm-symbolizer"
|
||||
|
||||
# Use a newer binutils, from the tooltool gcc package, if it's there
|
||||
if [ -e "$topsrcdir/gcc/bin/ld" ]; then
|
||||
export CC="$CC -B $topsrcdir/gcc/bin"
|
||||
export CXX="$CXX -B $topsrcdir/gcc/bin"
|
||||
# Use a newer binutils, if it's there
|
||||
if [ -e "$topsrcdir/binutils/bin/ld" ]; then
|
||||
export CC="$CC -B $topsrcdir/binutils/bin"
|
||||
export CXX="$CXX -B $topsrcdir/binutils/bin"
|
||||
fi
|
||||
|
||||
# Enable TSan specific code and build workarounds
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
const {
|
||||
CLEAR_FLEXBOX,
|
||||
TOGGLE_FLEX_ITEM_SHOWN,
|
||||
UPDATE_FLEXBOX,
|
||||
UPDATE_FLEXBOX_COLOR,
|
||||
UPDATE_FLEXBOX_HIGHLIGHTED,
|
||||
|
@ -22,6 +23,21 @@ module.exports = {
|
|||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggles the display of flex item sizing information shown for the given flex item
|
||||
* actor ID.
|
||||
*
|
||||
* @param {NodeFront} nodeFront
|
||||
* The NodeFront of the flex item to toggle the sizing information displayed
|
||||
* for.
|
||||
*/
|
||||
toggleFlexItemShown(nodeFront) {
|
||||
return {
|
||||
type: TOGGLE_FLEX_ITEM_SHOWN,
|
||||
nodeFront,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the flexbox state with the newly selected flexbox.
|
||||
*/
|
||||
|
|
|
@ -11,6 +11,9 @@ createEnum([
|
|||
// Clears the flexbox state by resetting it back to the initial flexbox state.
|
||||
"CLEAR_FLEXBOX",
|
||||
|
||||
// Toggles the display of flex item sizing information shown.
|
||||
"TOGGLE_FLEX_ITEM_SHOWN",
|
||||
|
||||
// Updates the flexbox state with the newly selected flexbox.
|
||||
"UPDATE_FLEXBOX",
|
||||
|
||||
|
|
|
@ -11,10 +11,12 @@ const { getStr } = require("devtools/client/inspector/layout/utils/l10n");
|
|||
|
||||
const ComputedProperty = createFactory(require("devtools/client/inspector/layout/components/ComputedProperty"));
|
||||
|
||||
const Types = require("../types");
|
||||
|
||||
class FlexContainerProperties extends PureComponent {
|
||||
static get propTypes() {
|
||||
return {
|
||||
properties: PropTypes.object.isRequired,
|
||||
properties: PropTypes.shape(Types.flexContainerProperties).isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -20,20 +20,32 @@ class FlexItem extends PureComponent {
|
|||
static get propTypes() {
|
||||
return {
|
||||
flexItem: PropTypes.shape(Types.flexItem).isRequired,
|
||||
onToggleFlexItemShown: PropTypes.func.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { flexItem } = this.props;
|
||||
const {
|
||||
flexItem,
|
||||
onToggleFlexItemShown,
|
||||
} = this.props;
|
||||
const { nodeFront } = flexItem;
|
||||
|
||||
return (
|
||||
dom.li({},
|
||||
Rep({
|
||||
defaultRep: ElementNode,
|
||||
mode: MODE.TINY,
|
||||
object: translateNodeFrontToGrip(nodeFront)
|
||||
})
|
||||
dom.button(
|
||||
{
|
||||
className: "devtools-button devtools-monospace",
|
||||
onClick: () => onToggleFlexItemShown(nodeFront),
|
||||
},
|
||||
Rep(
|
||||
{
|
||||
defaultRep: ElementNode,
|
||||
mode: MODE.TINY,
|
||||
object: translateNodeFrontToGrip(nodeFront)
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,18 +16,23 @@ class FlexItemList extends PureComponent {
|
|||
static get propTypes() {
|
||||
return {
|
||||
flexItems: PropTypes.arrayOf(PropTypes.shape(Types.flexItem)).isRequired,
|
||||
onToggleFlexItemShown: PropTypes.func.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { flexItems } = this.props;
|
||||
const {
|
||||
flexItems,
|
||||
onToggleFlexItemShown,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
dom.ol(
|
||||
{ id: "flex-item-list" },
|
||||
{ className: "flex-item-list" },
|
||||
flexItems.map(flexItem => FlexItem({
|
||||
key: flexItem.actorID,
|
||||
flexItem,
|
||||
onToggleFlexItemShown,
|
||||
}))
|
||||
)
|
||||
);
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { PureComponent } = require("devtools/client/shared/vendor/react");
|
||||
const dom = require("devtools/client/shared/vendor/react-dom-factories");
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
const { getStr } = require("devtools/client/inspector/layout/utils/l10n");
|
||||
|
||||
const Types = require("../types");
|
||||
|
||||
class FlexItemSizingProperties extends PureComponent {
|
||||
static get propTypes() {
|
||||
return {
|
||||
flexDirection: PropTypes.string.isRequired,
|
||||
flexItem: PropTypes.shape(Types.flexItem).isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
flexDirection,
|
||||
flexItem,
|
||||
} = this.props;
|
||||
const {
|
||||
flexItemSizing,
|
||||
properties,
|
||||
} = flexItem;
|
||||
const dimension = flexDirection.startsWith("row") ? "width" : "height";
|
||||
const contentStr = dimension === "width" ?
|
||||
getStr("flexbox.contentWidth") : getStr("flexbox.contentHeight");
|
||||
const finalStr = dimension === "width" ?
|
||||
getStr("flexbox.finalWidth") : getStr("flexbox.finalHeight");
|
||||
|
||||
return (
|
||||
dom.ol(
|
||||
{
|
||||
id: "flex-item-sizing-properties",
|
||||
className: "flex-item-list",
|
||||
},
|
||||
dom.li({},
|
||||
dom.span({}, "flex-basis: "),
|
||||
properties["flex-basis"]
|
||||
),
|
||||
dom.li({},
|
||||
dom.span({}, "flex-grow: "),
|
||||
properties["flex-grow"]
|
||||
),
|
||||
dom.li({},
|
||||
dom.span({}, "flex-shrink: "),
|
||||
properties["flex-shrink"]
|
||||
),
|
||||
dom.li({},
|
||||
dom.span({}, `${contentStr} `),
|
||||
`${parseFloat(flexItemSizing.mainBaseSize.toPrecision(6))}px`
|
||||
),
|
||||
dom.li({},
|
||||
dom.span({}, `Min-${dimension}: `),
|
||||
properties["min-" + dimension]
|
||||
),
|
||||
dom.li({},
|
||||
dom.span({}, `Max-${dimension}: `),
|
||||
properties["max-" + dimension]
|
||||
),
|
||||
dom.li({},
|
||||
dom.span({}, `${finalStr} `),
|
||||
`${parseFloat(properties[dimension].toPrecision(6))}px`
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FlexItemSizingProperties;
|
|
@ -18,6 +18,9 @@ loader.lazyGetter(this, "FlexContainerProperties", function() {
|
|||
loader.lazyGetter(this, "FlexItemList", function() {
|
||||
return createFactory(require("./FlexItemList"));
|
||||
});
|
||||
loader.lazyGetter(this, "FlexItemSizingProperties", function() {
|
||||
return createFactory(require("./FlexItemSizingProperties"));
|
||||
});
|
||||
|
||||
const Types = require("../types");
|
||||
|
||||
|
@ -30,11 +33,38 @@ class Flexbox extends PureComponent {
|
|||
onSetFlexboxOverlayColor: PropTypes.func.isRequired,
|
||||
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
|
||||
onToggleFlexboxHighlighter: PropTypes.func.isRequired,
|
||||
onToggleFlexItemShown: PropTypes.func.isRequired,
|
||||
setSelectedNode: PropTypes.func.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
renderFlexItemList() {
|
||||
const {
|
||||
flexbox,
|
||||
onToggleFlexItemShown,
|
||||
} = this.props;
|
||||
const {
|
||||
flexItems,
|
||||
highlighted,
|
||||
} = flexbox;
|
||||
|
||||
if (!highlighted || !flexItems.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const selectedFlexItem = flexItems.find(item => item.shown);
|
||||
|
||||
if (selectedFlexItem) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return FlexItemList({
|
||||
flexItems,
|
||||
onToggleFlexItemShown,
|
||||
});
|
||||
}
|
||||
|
||||
renderFlexItemSizingProperties() {
|
||||
const { flexbox } = this.props;
|
||||
const {
|
||||
flexItems,
|
||||
|
@ -45,8 +75,15 @@ class Flexbox extends PureComponent {
|
|||
return null;
|
||||
}
|
||||
|
||||
return FlexItemList({
|
||||
flexItems,
|
||||
const selectedFlexItem = flexItems.find(item => item.shown);
|
||||
|
||||
if (!selectedFlexItem) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return FlexItemSizingProperties({
|
||||
flexDirection: flexbox.properties["flex-direction"],
|
||||
flexItem: selectedFlexItem,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -81,6 +118,7 @@ class Flexbox extends PureComponent {
|
|||
setSelectedNode,
|
||||
}),
|
||||
this.renderFlexItemList(),
|
||||
this.renderFlexItemSizingProperties(),
|
||||
FlexContainerProperties({
|
||||
properties: flexbox.properties,
|
||||
})
|
||||
|
|
|
@ -10,4 +10,5 @@ DevToolsModules(
|
|||
'FlexContainerProperties.js',
|
||||
'FlexItem.js',
|
||||
'FlexItemList.js',
|
||||
'FlexItemSizingProperties.js',
|
||||
)
|
||||
|
|
|
@ -8,6 +8,7 @@ const { throttle } = require("devtools/client/inspector/shared/utils");
|
|||
|
||||
const {
|
||||
clearFlexbox,
|
||||
toggleFlexItemShown,
|
||||
updateFlexbox,
|
||||
updateFlexboxColor,
|
||||
updateFlexboxHighlighted,
|
||||
|
@ -31,6 +32,7 @@ class FlexboxInspector {
|
|||
this.onSetFlexboxOverlayColor = this.onSetFlexboxOverlayColor.bind(this);
|
||||
this.onSidebarSelect = this.onSidebarSelect.bind(this);
|
||||
this.onToggleFlexboxHighlighter = this.onToggleFlexboxHighlighter.bind(this);
|
||||
this.onToggleFlexItemShown = this.onToggleFlexItemShown.bind(this);
|
||||
this.onUpdatePanel = this.onUpdatePanel.bind(this);
|
||||
|
||||
this.init();
|
||||
|
@ -95,6 +97,7 @@ class FlexboxInspector {
|
|||
return {
|
||||
onSetFlexboxOverlayColor: this.onSetFlexboxOverlayColor,
|
||||
onToggleFlexboxHighlighter: this.onToggleFlexboxHighlighter,
|
||||
onToggleFlexItemShown: this.onToggleFlexItemShown,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -256,7 +259,7 @@ class FlexboxInspector {
|
|||
* Toggles on/off the flexbox highlighter for the provided flex container element.
|
||||
*
|
||||
* @param {NodeFront} node
|
||||
* The NodeFront of the flexb container element for which the flexbox
|
||||
* The NodeFront of the flex container element for which the flexbox
|
||||
* highlighter is toggled on/off for.
|
||||
*/
|
||||
onToggleFlexboxHighlighter(node) {
|
||||
|
@ -265,6 +268,19 @@ class FlexboxInspector {
|
|||
this.highlighters.flexboxHighlighterShow));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for a change in the input checkbox in the FlexItem component.
|
||||
* Toggles on/off the flex item highlighter for the provided flex item element.
|
||||
*
|
||||
* @param {NodeFront} node
|
||||
* The NodeFront of the flex item element for which the flex item is toggled
|
||||
* on/off for.
|
||||
*/
|
||||
onToggleFlexItemShown(node) {
|
||||
this.highlighters.toggleFlexItemHighlighter(node);
|
||||
this.store.dispatch(toggleFlexItemShown(node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for "new-root" event fired by the inspector and "new-node-front" event fired
|
||||
* by the inspector selection. Updates the flexbox panel if it is visible.
|
||||
|
@ -354,6 +370,7 @@ class FlexboxInspector {
|
|||
|
||||
flexItems.push({
|
||||
actorID: flexItemFront.actorID,
|
||||
shown: false,
|
||||
flexItemSizing: flexItemFront.flexItemSizing,
|
||||
nodeFront: itemNodeFront,
|
||||
properties: flexItemFront.properties,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
const {
|
||||
CLEAR_FLEXBOX,
|
||||
TOGGLE_FLEX_ITEM_SHOWN,
|
||||
UPDATE_FLEXBOX,
|
||||
UPDATE_FLEXBOX_COLOR,
|
||||
UPDATE_FLEXBOX_HIGHLIGHTED,
|
||||
|
@ -32,6 +33,22 @@ const reducers = {
|
|||
return INITIAL_FLEXBOX;
|
||||
},
|
||||
|
||||
[TOGGLE_FLEX_ITEM_SHOWN](flexbox, { nodeFront }) {
|
||||
return Object.assign({}, flexbox, {
|
||||
flexItems: flexbox.flexItems.map(flexItem => {
|
||||
if (flexItem.nodeFront !== nodeFront) {
|
||||
return Object.assign({}, flexItem, {
|
||||
shown: false,
|
||||
});
|
||||
}
|
||||
|
||||
return Object.assign({}, flexItem, {
|
||||
shown: !flexItem.shown,
|
||||
});
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
[UPDATE_FLEXBOX](_, { flexbox }) {
|
||||
return flexbox;
|
||||
},
|
||||
|
|
|
@ -6,6 +6,64 @@
|
|||
|
||||
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
|
||||
|
||||
/**
|
||||
* A flex item computed style properties.
|
||||
*/
|
||||
const flexItemProperties = exports.flexItemProperties = {
|
||||
|
||||
// The computed value of flex-basis.
|
||||
"flex-basis": PropTypes.string,
|
||||
|
||||
// The computed value of flex-grow.
|
||||
"flex-grow": PropTypes.string,
|
||||
|
||||
// The computed value of min-height.
|
||||
"min-height": PropTypes.string,
|
||||
|
||||
// The computed value of min-width.
|
||||
"min-width": PropTypes.string,
|
||||
|
||||
// The computed value of max-height.
|
||||
"max-height": PropTypes.string,
|
||||
|
||||
// The computed value of max-width.
|
||||
"max-width": PropTypes.string,
|
||||
|
||||
// The computed height of the flex item element.
|
||||
"height": PropTypes.number,
|
||||
|
||||
// The computed width of the flex item element.
|
||||
"width": PropTypes.number,
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* A flex item sizing data.
|
||||
*/
|
||||
const flexItemSizing = exports.flexItemSizing = {
|
||||
|
||||
// The max size of the flex item in the cross axis.
|
||||
crossMaxSize: PropTypes.number,
|
||||
|
||||
// The min size of the flex item in the cross axis.
|
||||
crossMinSize: PropTypes.number,
|
||||
|
||||
// The size of the flex item in the main axis before the flex sizing algorithm is
|
||||
// applied. This is also called the "flex base size" in the spec.
|
||||
mainBaseSize: PropTypes.number,
|
||||
|
||||
// The value that the flex sizing algorithm "wants" to use to stretch or shrink the
|
||||
// item, before clamping to the item's main min and max sizes.
|
||||
mainDeltaSize: PropTypes.number,
|
||||
|
||||
// The max size of the flex item in the main axis.
|
||||
mainMaxSize: PropTypes.number,
|
||||
|
||||
// The min size of the flex item in the maxin axis.
|
||||
mainMinSize: PropTypes.number,
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* A flex item data.
|
||||
*/
|
||||
|
@ -15,13 +73,38 @@ const flexItem = exports.flexItem = {
|
|||
actorID: PropTypes.string,
|
||||
|
||||
// The flex item sizing data.
|
||||
flexItemSizing: PropTypes.object,
|
||||
flexItemSizing: PropTypes.shape(flexItemSizing),
|
||||
|
||||
// The NodeFront of the flex item.
|
||||
nodeFront: PropTypes.object,
|
||||
|
||||
// The computed style properties of the flex item.
|
||||
properties: PropTypes.object,
|
||||
properties: PropTypes.shape(flexItemProperties),
|
||||
|
||||
// Whether or not the flex item sizing information is shown.
|
||||
shown: PropTypes.bool,
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* A flex container computed style properties.
|
||||
*/
|
||||
const flexContainerProperties = exports.flexContainerProperties = {
|
||||
|
||||
// The computed value of align-content.
|
||||
"align-content": PropTypes.string,
|
||||
|
||||
// The computed value of align-items.
|
||||
"align-items": PropTypes.string,
|
||||
|
||||
// The computed value of flex-direction.
|
||||
"flex-direction": PropTypes.string,
|
||||
|
||||
// The computed value of flex-wrap.
|
||||
"flex-wrap": PropTypes.string,
|
||||
|
||||
// The computed value of justify-content.
|
||||
"justify-content": PropTypes.string,
|
||||
|
||||
};
|
||||
|
||||
|
@ -46,6 +129,6 @@ exports.flexbox = {
|
|||
nodeFront: PropTypes.object,
|
||||
|
||||
// The computed style properties of the flex container.
|
||||
properties: PropTypes.object,
|
||||
properties: PropTypes.shape(flexContainerProperties),
|
||||
|
||||
};
|
||||
|
|
|
@ -48,6 +48,7 @@ class LayoutApp extends PureComponent {
|
|||
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
|
||||
onShowGridOutlineHighlight: PropTypes.func.isRequired,
|
||||
onToggleFlexboxHighlighter: PropTypes.func.isRequired,
|
||||
onToggleFlexItemShown: PropTypes.func.isRequired,
|
||||
onToggleGeometryEditor: PropTypes.func.isRequired,
|
||||
onToggleGridHighlighter: PropTypes.func.isRequired,
|
||||
onToggleShowGridAreas: PropTypes.func.isRequired,
|
||||
|
|
|
@ -47,6 +47,7 @@ class LayoutView {
|
|||
const {
|
||||
onSetFlexboxOverlayColor,
|
||||
onToggleFlexboxHighlighter,
|
||||
onToggleFlexItemShown,
|
||||
} = this.flexboxInspector.getComponentProps();
|
||||
|
||||
this.gridInspector = new GridInspector(this.inspector, this.inspector.panelWin);
|
||||
|
@ -69,6 +70,7 @@ class LayoutView {
|
|||
onShowBoxModelHighlighterForNode,
|
||||
onShowGridOutlineHighlight,
|
||||
onToggleFlexboxHighlighter,
|
||||
onToggleFlexItemShown,
|
||||
onToggleGeometryEditor,
|
||||
onToggleGridHighlighter,
|
||||
onToggleShowGridAreas,
|
||||
|
|
|
@ -16,6 +16,13 @@ flexbox.noFlexboxeOnThisPage=Select a Flex container or item to continue.
|
|||
# properties in the Flexbox panel.
|
||||
flexbox.flexContainerProperties=Flex Container Properties
|
||||
|
||||
# LOCALIZATION NOTE (flexbox.contentWidth, flexbox.contentHeight, flexbox.finalWidth,
|
||||
# flexbox.finalHeight): Labels for the flex item sizing properties in the Flexbox panel.
|
||||
flexbox.contentWidth=Content width:
|
||||
flexbox.contentHeight=Content height:
|
||||
flexbox.finalWidth=Final width:
|
||||
flexbox.finalHeight=Final height:
|
||||
|
||||
# LOCALIZATION NOTE (layout.cannotShowGridOutline, layout.cannotSHowGridOutline.title):
|
||||
# In the case where the grid outline cannot be effectively displayed.
|
||||
layout.cannotShowGridOutline=Cannot show outline for this grid
|
||||
|
|
|
@ -110,14 +110,27 @@
|
|||
* Flex Item List
|
||||
*/
|
||||
|
||||
#flex-item-list {
|
||||
.flex-item-list {
|
||||
border-bottom: 1px solid var(--theme-splitter-color);
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
padding-inline-start: 34px;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
.flex-item-list .devtools-button {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flex Item Sizing Properties
|
||||
*/
|
||||
|
||||
#flex-item-sizing-properties span {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flex Container Properties
|
||||
*/
|
||||
|
|
|
@ -402,6 +402,10 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.ruleview-overridden-item .ruleview-namecontainer {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.ruleview-flex,
|
||||
.ruleview-grid,
|
||||
.ruleview-swatch {
|
||||
|
|
|
@ -81,6 +81,15 @@ ReplayDebugger.prototype = {
|
|||
return data;
|
||||
},
|
||||
|
||||
// Send a request that requires the child process to perform actions that
|
||||
// diverge from the recording. In such cases we want to be interacting with a
|
||||
// replaying process (if there is one), as recording child processes won't
|
||||
// provide useful responses to such requests.
|
||||
_sendRequestAllowDiverge(request) {
|
||||
RecordReplayControl.maybeSwitchToReplayingChild();
|
||||
return this._sendRequest(request);
|
||||
},
|
||||
|
||||
_setBreakpoint(handler, position, data) {
|
||||
const id = RecordReplayControl.setBreakpoint(handler, position);
|
||||
this._breakpoints.push({id, position, data});
|
||||
|
@ -162,7 +171,8 @@ ReplayDebugger.prototype = {
|
|||
},
|
||||
|
||||
findAllConsoleMessages() {
|
||||
return this._sendRequest({ type: "findConsoleMessages" });
|
||||
const messages = this._sendRequest({ type: "findConsoleMessages" });
|
||||
return messages.map(this._convertConsoleMessage.bind(this));
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
@ -261,6 +271,21 @@ ReplayDebugger.prototype = {
|
|||
return this._getFrame(NewestFrameIndex);
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Console Message methods
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
_convertConsoleMessage(message) {
|
||||
// Console API message arguments need conversion to debuggee values, but
|
||||
// other contents of the message can be left alone.
|
||||
if (message.messageType == "ConsoleAPI" && message.arguments) {
|
||||
for (let i = 0; i < message.arguments.length; i++) {
|
||||
message.arguments[i] = this._convertValue(message.arguments[i]);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Handlers
|
||||
/////////////////////////////////////////////////////////
|
||||
|
@ -306,7 +331,10 @@ ReplayDebugger.prototype = {
|
|||
() => handler.call(this, this.getNewestFrame()));
|
||||
},
|
||||
|
||||
_getNewConsoleMessage() { return this._sendRequest({ type: "getNewConsoleMessage" }); },
|
||||
_getNewConsoleMessage() {
|
||||
const message = this._sendRequest({ type: "getNewConsoleMessage" });
|
||||
return this._convertConsoleMessage(message);
|
||||
},
|
||||
|
||||
get onConsoleMessage() {
|
||||
return this._breakpointKindGetter("ConsoleMessage");
|
||||
|
@ -426,8 +454,12 @@ ReplayDebuggerFrame.prototype = {
|
|||
get live() { return true; },
|
||||
|
||||
eval(text, options) {
|
||||
const rv = this._dbg._sendRequest({ type: "frameEvaluate",
|
||||
index: this._data.index, text, options });
|
||||
const rv = this._dbg._sendRequestAllowDiverge({
|
||||
type: "frameEvaluate",
|
||||
index: this._data.index,
|
||||
text,
|
||||
options
|
||||
});
|
||||
return this._dbg._convertCompletionValue(rv);
|
||||
},
|
||||
|
||||
|
@ -565,7 +597,7 @@ ReplayDebuggerObject.prototype = {
|
|||
|
||||
_ensureProperties() {
|
||||
if (!this._properties) {
|
||||
const properties = this._dbg._sendRequest({
|
||||
const properties = this._dbg._sendRequestAllowDiverge({
|
||||
type: "getObjectProperties",
|
||||
id: this._data.id
|
||||
});
|
||||
|
@ -598,8 +630,8 @@ ReplayDebuggerObject.prototype = {
|
|||
asEnvironment: NYI,
|
||||
executeInGlobal: NYI,
|
||||
executeInGlobalWithBindings: NYI,
|
||||
makeDebuggeeValue: NYI,
|
||||
|
||||
makeDebuggeeValue: NotAllowed,
|
||||
preventExtensions: NotAllowed,
|
||||
seal: NotAllowed,
|
||||
freeze: NotAllowed,
|
||||
|
@ -633,8 +665,10 @@ ReplayDebuggerEnvironment.prototype = {
|
|||
|
||||
_ensureNames() {
|
||||
if (!this._names) {
|
||||
const names =
|
||||
this._dbg._sendRequest({ type: "getEnvironmentNames", id: this._data.id });
|
||||
const names = this._dbg._sendRequestAllowDiverge({
|
||||
type: "getEnvironmentNames",
|
||||
id: this._data.id
|
||||
});
|
||||
this._names = {};
|
||||
names.forEach(({ name, value }) => {
|
||||
this._names[name] = this._dbg._convertValue(value);
|
||||
|
|
|
@ -238,15 +238,33 @@ Services.obs.addObserver({
|
|||
|
||||
const contents = {};
|
||||
for (const id in apiMessage) {
|
||||
if (id != "wrappedJSObject") {
|
||||
if (id != "wrappedJSObject" && id != "arguments") {
|
||||
contents[id] = JSON.parse(JSON.stringify(apiMessage[id]));
|
||||
}
|
||||
}
|
||||
|
||||
// Message arguments are preserved as debuggee values.
|
||||
if (apiMessage.arguments) {
|
||||
contents.arguments = apiMessage.arguments.map(makeDebuggeeValue);
|
||||
}
|
||||
|
||||
newConsoleMessage("ConsoleAPI", null, contents);
|
||||
},
|
||||
}, "console-api-log-event");
|
||||
|
||||
function convertConsoleMessage(contents) {
|
||||
const result = {};
|
||||
for (const id in contents) {
|
||||
if (id == "arguments" && contents.messageType == "ConsoleAPI") {
|
||||
// Copy arguments over as debuggee values.
|
||||
result.arguments = contents.arguments.map(convertValue);
|
||||
} else {
|
||||
result[id] = contents[id];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Position Handler State
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -442,6 +460,16 @@ function convertCompletionValue(value) {
|
|||
throw new Error("Unexpected completion value");
|
||||
}
|
||||
|
||||
function makeDebuggeeValue(value) {
|
||||
if (value && typeof value == "object") {
|
||||
assert(!(value instanceof Debugger.Object));
|
||||
const global = Cu.getGlobalForObject(value);
|
||||
const dbgGlobal = dbg.makeGlobalObjectReference(global);
|
||||
return dbgGlobal.makeDebuggeeValue(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function ClearPausedState() {
|
||||
gPausedObjects = new IdMap();
|
||||
|
@ -647,11 +675,11 @@ const gRequestHandlers = {
|
|||
},
|
||||
|
||||
findConsoleMessages(request) {
|
||||
return gConsoleMessages;
|
||||
return gConsoleMessages.map(convertConsoleMessage);
|
||||
},
|
||||
|
||||
getNewConsoleMessage(request) {
|
||||
return gConsoleMessages[gConsoleMessages.length - 1];
|
||||
return convertConsoleMessage(gConsoleMessages[gConsoleMessages.length - 1]);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -422,11 +422,9 @@ WebConsoleActor.prototype =
|
|||
*/
|
||||
makeDebuggeeValue: function(value, useObjectGlobal) {
|
||||
if (this.dbg.replaying) {
|
||||
if (typeof value == "object") {
|
||||
throw new Error("Object makeDebuggeeValue not supported with replaying debugger");
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
// If we are replaying then any values we are operating on should already
|
||||
// be debuggee values.
|
||||
return value;
|
||||
}
|
||||
if (useObjectGlobal && isObject(value)) {
|
||||
try {
|
||||
|
|
|
@ -62,7 +62,8 @@ const UnsolicitedPauses = {
|
|||
"breakpoint": "breakpoint",
|
||||
"DOMEvent": "DOMEvent",
|
||||
"watchpoint": "watchpoint",
|
||||
"exception": "exception"
|
||||
"exception": "exception",
|
||||
"replayForcedPause": "replayForcedPause",
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -29,7 +29,7 @@ interface nsIPaymentActionRequest : nsISupports
|
|||
const uint32_t ABORT_ACTION = 4;
|
||||
const uint32_t COMPLETE_ACTION = 5;
|
||||
const uint32_t UPDATE_ACTION = 6;
|
||||
const uint32_t CLEANUP_ACTION = 7;
|
||||
const uint32_t CLOSE_ACTION = 7;
|
||||
|
||||
/*
|
||||
* The payment request identifier.
|
||||
|
|
|
@ -61,6 +61,20 @@ interface nsIPaymentUIService : nsISupports
|
|||
* generated by Gecko
|
||||
*/
|
||||
void updatePayment(in AString requestId);
|
||||
|
||||
/**
|
||||
* Close the payment UI for the specified PaymentRequest.
|
||||
* The implementation should clean up the PaymentRequest data saved in the UI
|
||||
* component and close the UI if the specified PaymentRequest is showing to
|
||||
* the user.
|
||||
* Notice when the method is called, that means the PaymentRequest is invalid
|
||||
* in nsIPaymentRequestService.
|
||||
* @param requestId - the request identify of the payment request.
|
||||
* Notice that this requestId is an internal request Id
|
||||
* generated by Gecko
|
||||
*/
|
||||
void closePayment(in AString requestId);
|
||||
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
|
|
@ -9,7 +9,6 @@ with Files("**"):
|
|||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDOMXULButtonElement.idl',
|
||||
'nsIDOMXULCheckboxElement.idl',
|
||||
'nsIDOMXULCommandDispatcher.idl',
|
||||
'nsIDOMXULContainerElement.idl',
|
||||
'nsIDOMXULControlElement.idl',
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIDOMXULLabeledControlEl.idl"
|
||||
|
||||
[scriptable, uuid(674965d9-aff4-411d-a382-7cb32c0f25a1)]
|
||||
interface nsIDOMXULCheckboxElement : nsIDOMXULLabeledControlElement {
|
||||
attribute boolean checked;
|
||||
};
|
|
@ -746,7 +746,7 @@ void
|
|||
PaymentRequest::RejectShowPayment(nsresult aRejectReason)
|
||||
{
|
||||
MOZ_ASSERT(mAcceptPromise);
|
||||
MOZ_ASSERT(ReadyForUpdate());
|
||||
MOZ_ASSERT(mState == eInteractive);
|
||||
|
||||
mAcceptPromise->MaybeReject(aRejectReason);
|
||||
mState = eClosed;
|
||||
|
@ -762,7 +762,6 @@ PaymentRequest::RespondShowPayment(const nsAString& aMethodName,
|
|||
nsresult aRv)
|
||||
{
|
||||
MOZ_ASSERT(mAcceptPromise);
|
||||
MOZ_ASSERT(ReadyForUpdate());
|
||||
MOZ_ASSERT(mState == eInteractive);
|
||||
|
||||
if (NS_FAILED(aRv)) {
|
||||
|
@ -866,6 +865,9 @@ PaymentRequest::UpdatePayment(JSContext* aCx, const PaymentDetailsUpdate& aDetai
|
|||
bool aDeferredShow)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aCx);
|
||||
if (mState != eInteractive) {
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
|
||||
if (NS_WARN_IF(!manager)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -883,6 +885,9 @@ PaymentRequest::AbortUpdate(nsresult aRv, bool aDeferredShow)
|
|||
{
|
||||
MOZ_ASSERT(NS_FAILED(aRv));
|
||||
|
||||
if (mState != eInteractive) {
|
||||
return;
|
||||
}
|
||||
// Close down any remaining user interface.
|
||||
RefPtr<PaymentRequestManager> manager = PaymentRequestManager::GetSingleton();
|
||||
MOZ_ASSERT(manager);
|
||||
|
@ -1094,7 +1099,7 @@ PaymentRequest::NotifyOwnerDocumentActivityChanged()
|
|||
|
||||
if (!doc->IsCurrentActiveDocument()) {
|
||||
RefPtr<PaymentRequestManager> mgr = PaymentRequestManager::GetSingleton();
|
||||
mgr->CleanupPayment(this);
|
||||
mgr->ClosePayment(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -524,7 +524,7 @@ PaymentRequestManager::UpdatePayment(JSContext* aCx,
|
|||
}
|
||||
|
||||
nsresult
|
||||
PaymentRequestManager::CleanupPayment(PaymentRequest* aRequest)
|
||||
PaymentRequestManager::ClosePayment(PaymentRequest* aRequest)
|
||||
{
|
||||
// for the case, the payment request is waiting for response from user.
|
||||
if (auto entry = mActivePayments.Lookup(aRequest)) {
|
||||
|
@ -535,7 +535,7 @@ PaymentRequestManager::CleanupPayment(PaymentRequest* aRequest)
|
|||
}
|
||||
nsAutoString requestId;
|
||||
aRequest->GetInternalId(requestId);
|
||||
IPCPaymentCleanupActionRequest action(requestId);
|
||||
IPCPaymentCloseActionRequest action(requestId);
|
||||
return SendRequestPayment(aRequest, action, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
const PaymentDetailsUpdate& aDetails,
|
||||
bool aRequestShipping,
|
||||
bool aDeferredShow);
|
||||
nsresult CleanupPayment(PaymentRequest* aRequest);
|
||||
nsresult ClosePayment(PaymentRequest* aRequest);
|
||||
|
||||
nsresult RespondPayment(PaymentRequest* aRequest,
|
||||
const IPCPaymentActionResponse& aResponse);
|
||||
|
|
|
@ -177,6 +177,10 @@ PaymentRequestService::LaunchUIAction(const nsAString& aRequestId, uint32_t aAct
|
|||
rv = uiService->UpdatePayment(aRequestId);
|
||||
break;
|
||||
}
|
||||
case nsIPaymentActionRequest::CLOSE_ACTION: {
|
||||
rv = uiService->ClosePayment(aRequestId);
|
||||
break;
|
||||
}
|
||||
default : {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -382,18 +386,20 @@ PaymentRequestService::RequestPayment(nsIPaymentActionRequest* aRequest)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case nsIPaymentActionRequest::CLEANUP_ACTION: {
|
||||
case nsIPaymentActionRequest::CLOSE_ACTION: {
|
||||
nsCOMPtr<nsIPaymentRequest> payment;
|
||||
rv = GetPaymentRequestById(requestId, getter_AddRefs(payment));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
rv = LaunchUIAction(requestId, type);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (mShowingRequest == payment) {
|
||||
// might need to notify the PaymentRequest is cleanup
|
||||
mShowingRequest = nullptr;
|
||||
}
|
||||
mRequestQueue.RemoveElement(payment);
|
||||
//RemoveActionCallback(requestId);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -417,6 +423,10 @@ PaymentRequestService::RespondPayment(nsIPaymentActionResponse* aResponse)
|
|||
return rv;
|
||||
}
|
||||
|
||||
if (!request) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPaymentActionCallback> callback;
|
||||
if (!mCallbackHashtable.Get(requestId, getter_AddRefs(callback))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
|
|
|
@ -105,7 +105,7 @@ struct IPCPaymentUpdateActionRequest
|
|||
nsString shippingOption;
|
||||
};
|
||||
|
||||
struct IPCPaymentCleanupActionRequest
|
||||
struct IPCPaymentCloseActionRequest
|
||||
{
|
||||
nsString requestId;
|
||||
};
|
||||
|
@ -118,7 +118,7 @@ union IPCPaymentActionRequest
|
|||
IPCPaymentAbortActionRequest;
|
||||
IPCPaymentCompleteActionRequest;
|
||||
IPCPaymentUpdateActionRequest;
|
||||
IPCPaymentCleanupActionRequest;
|
||||
IPCPaymentCloseActionRequest;
|
||||
};
|
||||
|
||||
struct IPCPaymentCanMakeActionResponse
|
||||
|
|
|
@ -147,10 +147,10 @@ PaymentRequestParent::RecvRequestPayment(const IPCPaymentActionRequest& aRequest
|
|||
MOZ_ASSERT(action);
|
||||
break;
|
||||
}
|
||||
case IPCPaymentActionRequest::TIPCPaymentCleanupActionRequest: {
|
||||
const IPCPaymentCleanupActionRequest& request = aRequest;
|
||||
case IPCPaymentActionRequest::TIPCPaymentCloseActionRequest: {
|
||||
const IPCPaymentCloseActionRequest& request = aRequest;
|
||||
rv = CreateActionRequest(request.requestId(),
|
||||
nsIPaymentActionRequest::CLEANUP_ACTION,
|
||||
nsIPaymentActionRequest::CLOSE_ACTION,
|
||||
getter_AddRefs(action));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
|
|
|
@ -74,6 +74,8 @@ const detailedResponseUI = {
|
|||
completePayment: completePaymentResponse,
|
||||
updatePayment: function(requestId) {
|
||||
},
|
||||
closePayment: function (requestId) {
|
||||
},
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||
};
|
||||
|
||||
|
@ -102,6 +104,8 @@ const simpleResponseUI = {
|
|||
completePayment: completePaymentResponse,
|
||||
updatePayment: function(requestId) {
|
||||
},
|
||||
closePayment: function(requestId) {
|
||||
},
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||
};
|
||||
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
|
||||
|
||||
function emitTestFail(message) {
|
||||
sendAsyncMessage("test-fail", message);
|
||||
}
|
||||
function emitTestPass(message) {
|
||||
sendAsyncMessage("test-pass", message);
|
||||
}
|
||||
|
||||
addMessageListener("cleanup-check", function() {
|
||||
const paymentEnum = paymentSrv.enumerate();
|
||||
if (paymentEnum.hasMoreElements()) {
|
||||
emitTestFail("Non-empty PaymentRequest queue in PaymentRequestService.");
|
||||
} else {
|
||||
emitTestPass("Got empty PaymentRequest queue in PaymentRequestService.");
|
||||
}
|
||||
sendAsyncMessage("cleanup-check-complete");
|
||||
});
|
||||
|
||||
var setPaymentNums = 0;
|
||||
|
||||
addMessageListener("payment-num-set", function() {
|
||||
setPaymentNums = 0;
|
||||
for (let payment of paymentSrv.enumerate()) {
|
||||
setPaymentNums = setPaymentNums + 1;
|
||||
}
|
||||
sendAsyncMessage("payment-num-set-complete");
|
||||
});
|
||||
|
||||
addMessageListener("payment-num-check", function(expectedNumPayments) {
|
||||
let numPayments = 0;
|
||||
for (let payment of paymentSrv.enumerate()) {
|
||||
numPayments = numPayments + 1;
|
||||
}
|
||||
if (numPayments !== expectedNumPayments + setPaymentNums) {
|
||||
emitTestFail("Expected '" + expectedNumPayments +
|
||||
"' PaymentRequests in PaymentRequestService" + ", but got '" +
|
||||
numPayments + "'.");
|
||||
} else {
|
||||
emitTestPass("Got expected '" + numPayments +
|
||||
"' PaymentRequests in PaymentRequestService.");
|
||||
}
|
||||
// force cleanup PaymentRequests for clear environment to next testcase.
|
||||
paymentSrv.cleanup();
|
||||
sendAsyncMessage("payment-num-check-complete");
|
||||
});
|
||||
|
||||
addMessageListener("teardown", function() {
|
||||
paymentSrv.setTestingUIService(null);
|
||||
sendAsyncMessage('teardown-complete');
|
||||
});
|
|
@ -0,0 +1,117 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService);
|
||||
|
||||
function emitTestFail(message) {
|
||||
sendAsyncMessage("test-fail", message);
|
||||
}
|
||||
function emitTestPass(message) {
|
||||
sendAsyncMessage("test-pass", message);
|
||||
}
|
||||
|
||||
addMessageListener("close-check", function() {
|
||||
const paymentEnum = paymentSrv.enumerate();
|
||||
if (paymentEnum.hasMoreElements()) {
|
||||
emitTestFail("Non-empty PaymentRequest queue in PaymentRequestService.");
|
||||
} else {
|
||||
emitTestPass("Got empty PaymentRequest queue in PaymentRequestService.");
|
||||
}
|
||||
sendAsyncMessage("close-check-complete");
|
||||
});
|
||||
|
||||
var setPaymentNums = 0;
|
||||
|
||||
addMessageListener("payment-num-set", function() {
|
||||
setPaymentNums = 0;
|
||||
const paymentEnum = paymentSrv.enumerate();
|
||||
while (paymentEnum.hasMoreElements()) {
|
||||
setPaymentNums = setPaymentNums + 1;
|
||||
paymentEnum.getNext();
|
||||
}
|
||||
sendAsyncMessage("payment-num-set-complete");
|
||||
});
|
||||
|
||||
addMessageListener("payment-num-check", function(expectedNumPayments) {
|
||||
const paymentEnum = paymentSrv.enumerate();
|
||||
let numPayments = 0;
|
||||
while (paymentEnum.hasMoreElements()) {
|
||||
numPayments = numPayments + 1;
|
||||
paymentEnum.getNext();
|
||||
}
|
||||
if (numPayments !== expectedNumPayments + setPaymentNums) {
|
||||
emitTestFail("Expected '" + expectedNumPayments +
|
||||
"' PaymentRequests in PaymentRequestService" + ", but got '" +
|
||||
numPayments + "'.");
|
||||
} else {
|
||||
emitTestPass("Got expected '" + numPayments +
|
||||
"' PaymentRequests in PaymentRequestService.");
|
||||
}
|
||||
// force cleanup PaymentRequests for clear environment to next testcase.
|
||||
paymentSrv.cleanup();
|
||||
sendAsyncMessage("payment-num-check-complete");
|
||||
});
|
||||
|
||||
var respondRequestId;
|
||||
|
||||
addMessageListener("reject-payment", (expectedError) => {
|
||||
try {
|
||||
const responseData = Cc["@mozilla.org/dom/payments/general-response-data;1"].
|
||||
createInstance(Ci.nsIGeneralResponseData);
|
||||
responseData.initData({});
|
||||
const showResponse = Cc["@mozilla.org/dom/payments/payment-show-action-response;1"].
|
||||
createInstance(Ci.nsIPaymentShowActionResponse);
|
||||
showResponse.init(respondRequestId,
|
||||
Ci.nsIPaymentActionResponse.PAYMENT_REJECTED,
|
||||
"", // payment method
|
||||
responseData, // payment method data
|
||||
"", // payer name
|
||||
"", // payer email
|
||||
""); // payer phone
|
||||
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||
emitTestPass("Reject PaymentRequest successfully");
|
||||
} catch (error) {
|
||||
if (expectedError) {
|
||||
if (error.name === "NS_ERROR_FAILURE") {
|
||||
emitTestPass("Got expected NS_ERROR_FAILURE when responding a closed PaymentRequest");
|
||||
sendAsyncMessage("reject-payment-complete");
|
||||
return;
|
||||
}
|
||||
}
|
||||
emitTestFail("Unexpected error '" + error.name +
|
||||
"' when reponding a closed PaymentRequest");
|
||||
}
|
||||
sendAsyncMessage("reject-payment-complete");
|
||||
});
|
||||
|
||||
addMessageListener("update-payment", () => {
|
||||
try {
|
||||
paymentSrv.changeShippingOption(respondRequestId, "");
|
||||
emitTestPass("Change shippingOption succefully");
|
||||
} catch (error) {
|
||||
emitTestFail("Unexpected error '" + error.name +
|
||||
"' when changing the shipping option");
|
||||
}
|
||||
sendAsyncMessage("update-payment-complete");
|
||||
});
|
||||
|
||||
const DummyUIService = {
|
||||
showPayment: (requestId => {respondRequestId = requestId}),
|
||||
abortPayment: (requestId) => {respondRequestId = requestId},
|
||||
completePayment: (requestId) => {respondRequestId = requestId},
|
||||
updatePayment: (requestId) => {respondRequestId = requestId},
|
||||
closePayment: (requestId) => {respondRequestId = requestId},
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||
};
|
||||
|
||||
paymentSrv.setTestingUIService(DummyUIService.QueryInterface(Ci.nsIPaymentUIService));
|
||||
|
||||
|
||||
addMessageListener("teardown", function() {
|
||||
paymentSrv.setTestingUIService(null);
|
||||
sendAsyncMessage('teardown-complete');
|
||||
});
|
|
@ -26,6 +26,7 @@ const InvalidDetailsUIService = {
|
|||
},
|
||||
completePayment(requestId) {},
|
||||
updatePayment(requestId) {},
|
||||
closePayment(requestId) {},
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||
};
|
||||
|
||||
|
|
|
@ -39,6 +39,8 @@ const UIService = {
|
|||
""); // payer phone
|
||||
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||
},
|
||||
closePayment: function(requestId) {
|
||||
},
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||
};
|
||||
|
||||
|
|
|
@ -71,6 +71,8 @@ const NormalUIService = {
|
|||
""); // payer phone
|
||||
paymentSrv.respondPayment(showResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||
},
|
||||
closePayment: function(requestId) {
|
||||
},
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||
};
|
||||
|
||||
|
|
|
@ -74,6 +74,8 @@ const TestingUIService = {
|
|||
paymentSrv.respondPayment(completeResponse.QueryInterface(Ci.nsIPaymentActionResponse));
|
||||
},
|
||||
updatePayment: updateRequest,
|
||||
closePayment: function(requestId) {
|
||||
},
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||
};
|
||||
|
||||
|
|
|
@ -150,6 +150,7 @@ const DummyUIService = {
|
|||
abortPayment: abortRequest,
|
||||
completePayment: completeRequest,
|
||||
updatePayment: updateRequest,
|
||||
closePayment: function(requestId) {},
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||
};
|
||||
|
||||
|
|
|
@ -146,6 +146,7 @@ const DummyUIService = {
|
|||
abortPayment: abortRequest,
|
||||
completePayment: completeRequest,
|
||||
updatePayment: updateRequest,
|
||||
closePayment: function(requestId) {},
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIPaymentUIService]),
|
||||
};
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ support-files =
|
|||
simple_payment_request.html
|
||||
echo_payment_request.html
|
||||
BasiccardChromeScript.js
|
||||
CleanupChromeScript.js
|
||||
ClosePaymentChromeScript.js
|
||||
ConstructorChromeScript.js
|
||||
CurrencyAmountValidationChromeScript.js
|
||||
DefaultData.js
|
||||
|
@ -25,7 +25,7 @@ run-if = nightly_build # Bug 1390018: Depends on the Nightly-only UI service
|
|||
skip-if = e10s # Bug 1408250: Don't expose PaymentRequest Constructor in non-e10s
|
||||
[test_canMakePayment.html]
|
||||
run-if = nightly_build # Bug 1390737: Depends on the Nightly-only UI service
|
||||
[test_cleanupPayment.html]
|
||||
[test_closePayment.html]
|
||||
[test_constructor.html]
|
||||
[test_currency_amount_validation.html]
|
||||
skip-if = (verify && debug)
|
||||
|
|
|
@ -14,25 +14,64 @@ const details = {
|
|||
amount: { currency: "USD", value: "55.00" },
|
||||
},
|
||||
};
|
||||
const updatedDetails = {
|
||||
id: "simple details",
|
||||
total: {
|
||||
label: "Donation",
|
||||
amount: { currency: "USD", value: "55.00" },
|
||||
},
|
||||
error: "",
|
||||
};
|
||||
|
||||
let request;
|
||||
let shippingChangedEvent;
|
||||
|
||||
let msg = "successful";
|
||||
try {
|
||||
request = new PaymentRequest(methods, details);
|
||||
request.onshippingoptionchange = (event) => {
|
||||
shippingChangedEvent = event;
|
||||
window.parent.postMessage("successful", "*");
|
||||
};
|
||||
request.onshippingaddresschange = (event) => {
|
||||
shippingChangedEvent = event;
|
||||
window.parent.postMessage("successful", "*");
|
||||
};
|
||||
|
||||
} catch (err) {
|
||||
msg = err.name;
|
||||
}
|
||||
window.parent.postMessage(msg, "*");
|
||||
|
||||
|
||||
if (request) {
|
||||
window.onmessage = async ({ data: action }) => {
|
||||
msg = "successful";
|
||||
switch (action) {
|
||||
case "show PaymentRequest":
|
||||
const responsePromise = request.show();
|
||||
window.parent.postMessage("successful", "*");
|
||||
window.parent.postMessage(msg, "*");
|
||||
try {
|
||||
await responsePromise;
|
||||
} catch (err) { /* graceful abort */ }
|
||||
} catch (err) {
|
||||
if (err.name !== "AbortError") {
|
||||
msg = err.name;
|
||||
}
|
||||
}
|
||||
window.parent.postMessage(msg, "*")
|
||||
break;
|
||||
case "updateWith PaymentRequest":
|
||||
if (shippingChangedEvent) {
|
||||
try {
|
||||
shippingChangedEvent.updateWith(updatedDetails);
|
||||
} catch(err) {
|
||||
if (err.name !== "InvalidStateError") {
|
||||
msg = err.name;
|
||||
}
|
||||
}
|
||||
window.parent.postMessage(msg, "*");
|
||||
shippingChangedEvent = undefined;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
window.parent.postMessage(`fail - unknown postmessage action: ${action}`, "*");
|
||||
|
|
|
@ -5,7 +5,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1408234
|
|||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1408234</title>
|
||||
<title>Test for closing PaymentRequest</title>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
@ -13,7 +13,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1408234
|
|||
"use strict";
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var gUrl = SimpleTest.getTestFileURL('CleanupChromeScript.js');
|
||||
var gUrl = SimpleTest.getTestFileURL('ClosePaymentChromeScript.js');
|
||||
var gScript = SpecialPowers.loadChromeScript(gUrl);
|
||||
var testName = "";
|
||||
|
||||
|
@ -25,40 +25,26 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1408234
|
|||
}
|
||||
gScript.addMessageListener("test-fail", testFailHandler);
|
||||
gScript.addMessageListener("test-pass", testPassHandler);
|
||||
|
||||
function cleanupCheck(resolveFunc) {
|
||||
gScript.addMessageListener("cleanup-check-complete", function checkCompleteHandler() {
|
||||
gScript.removeMessageListener("cleanup-check-complete", checkCompleteHandler);
|
||||
resolveFunc();
|
||||
|
||||
async function requestChromeAction(action, params) {
|
||||
gScript.sendAsyncMessage(action, params);
|
||||
await new Promise(resolve => {
|
||||
gScript.addMessageListener(`${action}-complete`, function completeListener() {
|
||||
gScript.removeMessageListener(`${action}-complete`, completeListener);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
gScript.sendAsyncMessage("cleanup-check");
|
||||
}
|
||||
|
||||
function paymentNumCheck(resolveFunc, numPayments) {
|
||||
gScript.addMessageListener("payment-num-check-complete", function checkCompleteHandler() {
|
||||
gScript.removeMessageListener("payment-num-check-complete", checkCompleteHandler);
|
||||
resolveFunc();
|
||||
});
|
||||
gScript.sendAsyncMessage("payment-num-check", numPayments);
|
||||
}
|
||||
|
||||
function paymentNumSet() {
|
||||
gScript.addMessageListener("payment-num-set-complete", function setCompleteHandler() {
|
||||
gScript.removeMessageListener("payment-num-set-complete", setCompleteHandler);
|
||||
});
|
||||
gScript.sendAsyncMessage("payment-num-set");
|
||||
}
|
||||
|
||||
function testCleanupByReloading() {
|
||||
paymentNumSet();
|
||||
return new Promise((resolve, reject) => {
|
||||
testName = "testCleanupByReloading";
|
||||
function testCloseByReloading() {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
testName = "testCloseByReloading";
|
||||
let expectedResults = ["successful", "successful"];
|
||||
let nextStatus = ["creating", "reloading"];
|
||||
let currStatus = nextStatus.shift();
|
||||
let ifr = document.createElement('iframe');
|
||||
|
||||
let listener = function(event) {
|
||||
await requestChromeAction("payment-num-set");
|
||||
let listener = async function(event) {
|
||||
let expected = expectedResults.shift();
|
||||
is(event.data, expected,
|
||||
testName + ": Expected '" + expected + "' when " + currStatus +
|
||||
|
@ -67,8 +53,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1408234
|
|||
ifr.contentWindow.location.reload();
|
||||
} else if (currStatus === "reloading") {
|
||||
window.removeEventListener("message", listener);
|
||||
paymentNumCheck(resolve, 1);
|
||||
await requestChromeAction("payment-num-check", 1);
|
||||
document.body.removeChild(ifr);
|
||||
resolve();
|
||||
}
|
||||
currStatus = nextStatus.shift();
|
||||
}
|
||||
|
@ -78,14 +65,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1408234
|
|||
});
|
||||
}
|
||||
|
||||
function testCleanupByRedirecting() {
|
||||
function testCloseByRedirecting() {
|
||||
return new Promise((resolve, reject) => {
|
||||
testName = "testCleanupByRedirecting";
|
||||
testName = "testCloseByRedirecting";
|
||||
let expectedResults = ["successful", "successful"];
|
||||
let nextStatus = ["creating", "redirecting"];
|
||||
let currStatus = nextStatus.shift();
|
||||
let ifr = document.createElement('iframe');
|
||||
let listener = function(event) {
|
||||
let listener = async function(event) {
|
||||
let expected = expectedResults.shift();
|
||||
is(event.data, expected,
|
||||
testName + ": Expected '" + expected + "' when " + currStatus +
|
||||
|
@ -94,8 +81,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1408234
|
|||
ifr.src = "blank_page.html";
|
||||
} else if (currStatus === "redirecting"){
|
||||
window.removeEventListener("message", listener);
|
||||
cleanupCheck(resolve);
|
||||
await requestChromeAction("close-check");
|
||||
document.body.removeChild(ifr);
|
||||
resolve();
|
||||
}
|
||||
currStatus = nextStatus.shift();
|
||||
};
|
||||
|
@ -105,27 +93,31 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1408234
|
|||
});
|
||||
}
|
||||
|
||||
function testCleanupByRedirectingAfterShow() {
|
||||
function testCloseByRedirectingAfterShow() {
|
||||
return new Promise((resolve, reject) => {
|
||||
testName = "testCleanupByRedirectingAfterShow";
|
||||
testName = "testCloseByRedirectingAfterShow";
|
||||
let nextStatus = ["creating", "showing", "redirecting"];
|
||||
let currStatus = nextStatus.shift();
|
||||
let expectedResults = ["successful", "successful", "successful"];
|
||||
let ifr = document.createElement('iframe');
|
||||
let listener = (event) => {
|
||||
let handler = undefined;
|
||||
let listener = async (event) => {
|
||||
let expected = expectedResults.shift();
|
||||
is(event.data, expected,
|
||||
testName + ": Expected '" + expected + "' when " + currStatus +
|
||||
", but got '" + event.data + "'");
|
||||
|
||||
if (currStatus === "creating") {
|
||||
handler = SpecialPowers.getDOMWindowUtils(ifr.contentWindow).setHandlingUserInput(true);
|
||||
ifr.contentWindow.postMessage("show PaymentRequest", "*");
|
||||
} else if (currStatus === "showing") {
|
||||
handler.destruct();
|
||||
ifr.src = "blank_page.html";
|
||||
} else if (currStatus === "redirecting") {
|
||||
window.removeEventListener("message", listener);
|
||||
cleanupCheck(resolve);
|
||||
await requestChromeAction("close-check");
|
||||
await requestChromeAction("reject-payment", true);
|
||||
document.body.removeChild(ifr);
|
||||
resolve();
|
||||
}
|
||||
currStatus = nextStatus.shift();
|
||||
}
|
||||
|
@ -135,21 +127,22 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1408234
|
|||
});
|
||||
}
|
||||
|
||||
function testCleanupByRemovingIframe() {
|
||||
function testCloseByRemovingIframe() {
|
||||
return new Promise((resolve, reject) => {
|
||||
testName = "testCleanupByRemovingIframe";
|
||||
testName = "testCloseByRemovingIframe";
|
||||
let expectedResults = ["successful"];
|
||||
let nextStatus = ["creating"];
|
||||
let currStatus = nextStatus.shift();
|
||||
let ifr = document.createElement('iframe');
|
||||
let listener = function(event) {
|
||||
let listener = async function(event) {
|
||||
let expected = expectedResults.shift();
|
||||
is(event.data, expected,
|
||||
testName + ": Expected '" + expected + "' when " + currStatus +
|
||||
", but got '" + event.data + "'");
|
||||
document.body.removeChild(ifr);
|
||||
window.removeEventListener("message", listener);
|
||||
cleanupCheck(resolve);
|
||||
await requestChromeAction("close-check");
|
||||
resolve();
|
||||
};
|
||||
window.addEventListener("message", listener);
|
||||
ifr.src = "simple_payment_request.html";
|
||||
|
@ -157,18 +150,70 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1408234
|
|||
});
|
||||
}
|
||||
|
||||
function testUpdateWithRespondedPayment() {
|
||||
return new Promise(resolve => {
|
||||
testName = "testUpdateWithRespondedPayment";
|
||||
let nextStatus = ["creating", "showing", "closing", "updating", "finishing"];
|
||||
let currStatus = nextStatus.shift();
|
||||
let ifr = document.createElement('iframe');
|
||||
let handler = undefined;
|
||||
let listener = async function(event) {
|
||||
is(event.data, "successful",
|
||||
testName + ": Expected 'successful' when " + currStatus +
|
||||
", but got '" + event.data + "'");
|
||||
switch (currStatus) {
|
||||
case "creating":
|
||||
handler = SpecialPowers.getDOMWindowUtils(ifr.contentWindow).setHandlingUserInput(true);
|
||||
ifr.contentWindow.postMessage("show PaymentRequest", "*");
|
||||
break;
|
||||
case "showing":
|
||||
await requestChromeAction("update-payment");
|
||||
break;
|
||||
case "closing":
|
||||
await requestChromeAction("reject-payment", false);
|
||||
break;
|
||||
case "updating":
|
||||
await requestChromeAction("close-check");
|
||||
ifr.contentWindow.postMessage("updateWith PaymentRequest", "*");
|
||||
break;
|
||||
case "finishing":
|
||||
handler.destruct();
|
||||
document.body.removeChild(ifr);
|
||||
window.removeEventListener("message", listener);
|
||||
resolve();
|
||||
break;
|
||||
default:
|
||||
ok(false, testName + ": Unknown status()" + currStatus);
|
||||
break;
|
||||
}
|
||||
currStatus = nextStatus.shift();
|
||||
}
|
||||
window.addEventListener("message", listener);
|
||||
ifr.src = "simple_payment_request.html";
|
||||
document.body.appendChild(ifr);
|
||||
});
|
||||
}
|
||||
|
||||
function teardown() {
|
||||
gScript.removeMessageListener("test-fail", testFailHandler);
|
||||
gScript.removeMessageListener("test-pass", testPassHandler);
|
||||
gScript.destroy();
|
||||
SimpleTest.finish();
|
||||
return new Promise((resolve, reject) => {
|
||||
gScript.addMessageListener("teardown-complete", function teardownCompleteHandler() {
|
||||
gScript.removeMessageListener("teardown-complete", teardownCompleteHandler);
|
||||
gScript.removeMessageListener("test-fail", testFailHandler);
|
||||
gScript.removeMessageListener("test-pass", testPassHandler);
|
||||
gScript.destroy();
|
||||
SimpleTest.finish();
|
||||
resolve();
|
||||
});
|
||||
gScript.sendAsyncMessage("teardown");
|
||||
});
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
testCleanupByReloading()
|
||||
.then(testCleanupByRedirecting)
|
||||
.then(testCleanupByRedirectingAfterShow)
|
||||
.then(testCleanupByRemovingIframe)
|
||||
testCloseByReloading()
|
||||
.then(testCloseByRedirecting)
|
||||
.then(testCloseByRedirectingAfterShow)
|
||||
.then(testCloseByRemovingIframe)
|
||||
.then(testUpdateWithRespondedPayment)
|
||||
.then(teardown)
|
||||
.catch( e => {
|
||||
ok(false, "Unexpected error: " + e.name);
|
||||
|
@ -187,5 +232,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1408234
|
|||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1408234">Mozilla Bug 1408234</a>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1483470">Mozilla Bug 1483470</a>
|
||||
</body>
|
||||
</html>
|
|
@ -188,19 +188,14 @@ function GetModuleNamespace(module)
|
|||
// Step 1
|
||||
assert(IsObject(module) && IsModule(module), "GetModuleNamespace called with non-module");
|
||||
|
||||
// Until issue https://github.com/tc39/ecma262/issues/1155 is resolved,
|
||||
// violate the spec here and throw if called on an errored module.
|
||||
if (module.status === MODULE_STATUS_EVALUATED_ERROR)
|
||||
throw GetModuleEvaluationError(module);
|
||||
|
||||
// Steps 2-3
|
||||
// Step 2
|
||||
assert(module.status !== MODULE_STATUS_UNINSTANTIATED,
|
||||
"Bad module state in GetModuleNamespace");
|
||||
|
||||
// Step 4
|
||||
// Step 3
|
||||
let namespace = module.namespace;
|
||||
|
||||
// Step 3
|
||||
// Step 4
|
||||
if (typeof namespace === "undefined") {
|
||||
let exportedNames = callFunction(module.getExportedNames, module);
|
||||
let unambiguousNames = [];
|
||||
|
@ -213,7 +208,7 @@ function GetModuleNamespace(module)
|
|||
namespace = ModuleNamespaceCreate(module, unambiguousNames);
|
||||
}
|
||||
|
||||
// Step 4
|
||||
// Step 5
|
||||
return namespace;
|
||||
}
|
||||
|
||||
|
|
|
@ -1655,8 +1655,8 @@ obj_entries(JSContext* cx, unsigned argc, Value* vp)
|
|||
}
|
||||
|
||||
/* ES6 draft 15.2.3.16 */
|
||||
static bool
|
||||
obj_is(JSContext* cx, unsigned argc, Value* vp)
|
||||
bool
|
||||
js::obj_is(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
|
|
|
@ -35,6 +35,9 @@ obj_propertyIsEnumerable(JSContext* cx, unsigned argc, Value* vp);
|
|||
MOZ_MUST_USE bool
|
||||
obj_create(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
obj_is(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
MOZ_MUST_USE bool
|
||||
obj_getOwnPropertyNames(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
|
|
|
@ -110,15 +110,6 @@ function ToLength(v) {
|
|||
return std_Math_min(v, 0x1fffffffffffff);
|
||||
}
|
||||
|
||||
// ES2017 draft rev aebf014403a3e641fb1622aec47c40f051943527
|
||||
// 7.2.9 SameValue ( x, y )
|
||||
function SameValue(x, y) {
|
||||
if (x === y) {
|
||||
return (x !== 0) || (1 / x === 1 / y);
|
||||
}
|
||||
return (x !== x && y !== y);
|
||||
}
|
||||
|
||||
// ES2017 draft rev aebf014403a3e641fb1622aec47c40f051943527
|
||||
// 7.2.10 SameValueZero ( x, y )
|
||||
function SameValueZero(x, y) {
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// A generator is left closed after frame.onPop returns a {return:} resumption value.
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger;
|
||||
var gw = dbg.addDebuggee(g);
|
||||
dbg.onDebuggerStatement = frame => {
|
||||
frame.onPop = completion => ({return: "ok"});
|
||||
};
|
||||
g.eval("function* g() { for (var i = 0; i < 10; i++) { debugger; yield i; } }");
|
||||
var it = g.g();
|
||||
var result = it.next();
|
||||
assertEq(result.value, "ok");
|
||||
assertEq(result.done, true);
|
||||
assertEq(it.next().value, undefined);
|
|
@ -0,0 +1,19 @@
|
|||
"use strict";
|
||||
|
||||
load(libdir + "asserts.js");
|
||||
load(libdir + "dummyModuleResolveHook.js");
|
||||
|
||||
class UniqueError extends Error {}
|
||||
|
||||
let a = moduleRepo['a'] = parseModule(`
|
||||
throw new UniqueError();
|
||||
`);
|
||||
|
||||
let b = moduleRepo['b'] = parseModule(`
|
||||
import * as ns0 from "a";
|
||||
`);
|
||||
|
||||
instantiateModule(a);
|
||||
assertThrowsInstanceOf(() => evaluateModule(a), UniqueError);
|
||||
instantiateModule(b);
|
||||
assertThrowsInstanceOf(() => evaluateModule(b), UniqueError);
|
|
@ -32,4 +32,5 @@ assertThrowsMyError(() => evaluateModule(c));
|
|||
let b = moduleRepo['b'] = parseModule(`
|
||||
import * as ns0 from 'a'
|
||||
`);
|
||||
assertThrowsMyError(() => instantiateModule(b));
|
||||
instantiateModule(b);
|
||||
assertThrowsMyError(() => evaluateModule(b));
|
||||
|
|
|
@ -424,57 +424,6 @@ BaselineCacheIRCompiler::emitGuardSpecificSymbol()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitGuardXrayExpandoShapeAndDefaultProto()
|
||||
{
|
||||
Register obj = allocator.useRegister(masm, reader.objOperandId());
|
||||
bool hasExpando = reader.readBool();
|
||||
Address shapeWrapperAddress(stubAddress(reader.stubOffset()));
|
||||
|
||||
AutoScratchRegister scratch(allocator, masm);
|
||||
Maybe<AutoScratchRegister> scratch2, scratch3;
|
||||
if (hasExpando) {
|
||||
scratch2.emplace(allocator, masm);
|
||||
scratch3.emplace(allocator, masm);
|
||||
}
|
||||
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
masm.loadPtr(Address(obj, ProxyObject::offsetOfReservedSlots()), scratch);
|
||||
Address holderAddress(scratch, sizeof(Value) * GetXrayJitInfo()->xrayHolderSlot);
|
||||
Address expandoAddress(scratch, NativeObject::getFixedSlotOffset(GetXrayJitInfo()->holderExpandoSlot));
|
||||
|
||||
if (hasExpando) {
|
||||
masm.branchTestObject(Assembler::NotEqual, holderAddress, failure->label());
|
||||
masm.unboxObject(holderAddress, scratch);
|
||||
masm.branchTestObject(Assembler::NotEqual, expandoAddress, failure->label());
|
||||
masm.unboxObject(expandoAddress, scratch);
|
||||
|
||||
// Unwrap the expando before checking its shape.
|
||||
masm.loadPtr(Address(scratch, ProxyObject::offsetOfReservedSlots()), scratch);
|
||||
masm.unboxObject(Address(scratch, js::detail::ProxyReservedSlots::offsetOfPrivateSlot()), scratch);
|
||||
|
||||
masm.loadPtr(shapeWrapperAddress, scratch2.ref());
|
||||
LoadShapeWrapperContents(masm, scratch2.ref(), scratch2.ref(), failure->label());
|
||||
masm.branchTestObjShape(Assembler::NotEqual, scratch, *scratch2, *scratch3, scratch,
|
||||
failure->label());
|
||||
|
||||
// The reserved slots on the expando should all be in fixed slots.
|
||||
Address protoAddress(scratch, NativeObject::getFixedSlotOffset(GetXrayJitInfo()->expandoProtoSlot));
|
||||
masm.branchTestUndefined(Assembler::NotEqual, protoAddress, failure->label());
|
||||
} else {
|
||||
Label done;
|
||||
masm.branchTestObject(Assembler::NotEqual, holderAddress, &done);
|
||||
masm.unboxObject(holderAddress, scratch);
|
||||
masm.branchTestObject(Assembler::Equal, expandoAddress, failure->label());
|
||||
masm.bind(&done);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCacheIRCompiler::emitLoadValueResult()
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@ using namespace js;
|
|||
using namespace js::jit;
|
||||
|
||||
using mozilla::BitwiseCast;
|
||||
using mozilla::Maybe;
|
||||
|
||||
ValueOperand
|
||||
CacheRegisterAllocator::useValueRegister(MacroAssembler& masm, ValOperandId op)
|
||||
|
@ -2682,6 +2683,57 @@ CacheIRCompiler::emitGuardTagNotEqual()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitGuardXrayExpandoShapeAndDefaultProto()
|
||||
{
|
||||
Register obj = allocator.useRegister(masm, reader.objOperandId());
|
||||
bool hasExpando = reader.readBool();
|
||||
StubFieldOffset shapeWrapper(reader.stubOffset(), StubField::Type::JSObject);
|
||||
|
||||
AutoScratchRegister scratch(allocator, masm);
|
||||
Maybe<AutoScratchRegister> scratch2, scratch3;
|
||||
if (hasExpando) {
|
||||
scratch2.emplace(allocator, masm);
|
||||
scratch3.emplace(allocator, masm);
|
||||
}
|
||||
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
masm.loadPtr(Address(obj, ProxyObject::offsetOfReservedSlots()), scratch);
|
||||
Address holderAddress(scratch, sizeof(Value) * GetXrayJitInfo()->xrayHolderSlot);
|
||||
Address expandoAddress(scratch, NativeObject::getFixedSlotOffset(GetXrayJitInfo()->holderExpandoSlot));
|
||||
|
||||
if (hasExpando) {
|
||||
masm.branchTestObject(Assembler::NotEqual, holderAddress, failure->label());
|
||||
masm.unboxObject(holderAddress, scratch);
|
||||
masm.branchTestObject(Assembler::NotEqual, expandoAddress, failure->label());
|
||||
masm.unboxObject(expandoAddress, scratch);
|
||||
|
||||
// Unwrap the expando before checking its shape.
|
||||
masm.loadPtr(Address(scratch, ProxyObject::offsetOfReservedSlots()), scratch);
|
||||
masm.unboxObject(Address(scratch, js::detail::ProxyReservedSlots::offsetOfPrivateSlot()), scratch);
|
||||
|
||||
emitLoadStubField(shapeWrapper, scratch2.ref());
|
||||
LoadShapeWrapperContents(masm, scratch2.ref(), scratch2.ref(), failure->label());
|
||||
masm.branchTestObjShape(Assembler::NotEqual, scratch, *scratch2, *scratch3, scratch,
|
||||
failure->label());
|
||||
|
||||
// The reserved slots on the expando should all be in fixed slots.
|
||||
Address protoAddress(scratch, NativeObject::getFixedSlotOffset(GetXrayJitInfo()->expandoProtoSlot));
|
||||
masm.branchTestUndefined(Assembler::NotEqual, protoAddress, failure->label());
|
||||
} else {
|
||||
Label done;
|
||||
masm.branchTestObject(Assembler::NotEqual, holderAddress, &done);
|
||||
masm.unboxObject(holderAddress, scratch);
|
||||
masm.branchTestObject(Assembler::Equal, expandoAddress, failure->label());
|
||||
masm.bind(&done);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheIRCompiler::emitGuardNoAllocationMetadataBuilder()
|
||||
{
|
||||
|
|
|
@ -46,8 +46,9 @@ namespace jit {
|
|||
_(GuardAndGetIndexFromString) \
|
||||
_(GuardIndexIsNonNegative) \
|
||||
_(GuardTagNotEqual) \
|
||||
_(GuardXrayExpandoShapeAndDefaultProto)\
|
||||
_(GuardNoAllocationMetadataBuilder) \
|
||||
_(GuardObjectGroupNotPretenured) \
|
||||
_(GuardObjectGroupNotPretenured) \
|
||||
_(LoadObject) \
|
||||
_(LoadProto) \
|
||||
_(LoadEnclosingEnvironment) \
|
||||
|
|
|
@ -839,58 +839,6 @@ IonCacheIRCompiler::emitGuardSpecificSymbol()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonCacheIRCompiler::emitGuardXrayExpandoShapeAndDefaultProto()
|
||||
{
|
||||
Register obj = allocator.useRegister(masm, reader.objOperandId());
|
||||
bool hasExpando = reader.readBool();
|
||||
JSObject* shapeWrapper = objectStubField(reader.stubOffset());
|
||||
MOZ_ASSERT(hasExpando == !!shapeWrapper);
|
||||
|
||||
AutoScratchRegister scratch(allocator, masm);
|
||||
Maybe<AutoScratchRegister> scratch2, scratch3;
|
||||
if (hasExpando) {
|
||||
scratch2.emplace(allocator, masm);
|
||||
scratch3.emplace(allocator, masm);
|
||||
}
|
||||
|
||||
FailurePath* failure;
|
||||
if (!addFailurePath(&failure))
|
||||
return false;
|
||||
|
||||
masm.loadPtr(Address(obj, ProxyObject::offsetOfReservedSlots()), scratch);
|
||||
Address holderAddress(scratch, sizeof(Value) * GetXrayJitInfo()->xrayHolderSlot);
|
||||
Address expandoAddress(scratch, NativeObject::getFixedSlotOffset(GetXrayJitInfo()->holderExpandoSlot));
|
||||
|
||||
if (hasExpando) {
|
||||
masm.branchTestObject(Assembler::NotEqual, holderAddress, failure->label());
|
||||
masm.unboxObject(holderAddress, scratch);
|
||||
masm.branchTestObject(Assembler::NotEqual, expandoAddress, failure->label());
|
||||
masm.unboxObject(expandoAddress, scratch);
|
||||
|
||||
// Unwrap the expando before checking its shape.
|
||||
masm.loadPtr(Address(scratch, ProxyObject::offsetOfReservedSlots()), scratch);
|
||||
masm.unboxObject(Address(scratch, detail::ProxyReservedSlots::offsetOfPrivateSlot()), scratch);
|
||||
|
||||
masm.movePtr(ImmGCPtr(shapeWrapper), scratch2.ref());
|
||||
LoadShapeWrapperContents(masm, scratch2.ref(), scratch2.ref(), failure->label());
|
||||
masm.branchTestObjShape(Assembler::NotEqual, scratch, *scratch2, *scratch3, scratch,
|
||||
failure->label());
|
||||
|
||||
// The reserved slots on the expando should all be in fixed slots.
|
||||
Address protoAddress(scratch, NativeObject::getFixedSlotOffset(GetXrayJitInfo()->expandoProtoSlot));
|
||||
masm.branchTestUndefined(Assembler::NotEqual, protoAddress, failure->label());
|
||||
} else {
|
||||
Label done;
|
||||
masm.branchTestObject(Assembler::NotEqual, holderAddress, &done);
|
||||
masm.unboxObject(holderAddress, scratch);
|
||||
masm.branchTestObject(Assembler::Equal, expandoAddress, failure->label());
|
||||
masm.bind(&done);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonCacheIRCompiler::emitLoadValueResult()
|
||||
{
|
||||
|
|
|
@ -897,6 +897,47 @@ static void
|
|||
DebuggerFrame_maybeDecrementFrameScriptStepModeCount(FreeOp* fop, AbstractFramePtr frame,
|
||||
NativeObject* frameobj);
|
||||
|
||||
/*
|
||||
* RAII class to mark a generator as "running" temporarily while running
|
||||
* debugger code.
|
||||
*
|
||||
* When Debugger::slowPathOnLeaveFrame is called for a frame that is yielding
|
||||
* or awaiting, its generator is in the "suspended" state. Letting script
|
||||
* observe this state, with the generator on stack yet also reenterable, would
|
||||
* be bad, so we mark it running while we fire events.
|
||||
*/
|
||||
class MOZ_RAII AutoSetGeneratorRunning
|
||||
{
|
||||
int32_t yieldAwaitIndex_;
|
||||
Rooted<GeneratorObject*> genObj_;
|
||||
|
||||
public:
|
||||
AutoSetGeneratorRunning(JSContext* cx, Handle<GeneratorObject*> genObj)
|
||||
: yieldAwaitIndex_(0),
|
||||
genObj_(cx, genObj)
|
||||
{
|
||||
if (genObj) {
|
||||
if (!genObj->isBeforeInitialYield() && !genObj->isClosed() && genObj->isSuspended()) {
|
||||
yieldAwaitIndex_ =
|
||||
genObj->getFixedSlot(GeneratorObject::YIELD_AND_AWAIT_INDEX_SLOT).toInt32();
|
||||
genObj->setRunning();
|
||||
} else {
|
||||
// We're returning or throwing, not yielding or awaiting. The
|
||||
// generator is already closed, if it was ever exposed at all.
|
||||
genObj_ = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~AutoSetGeneratorRunning() {
|
||||
if (genObj_) {
|
||||
MOZ_ASSERT(genObj_->isRunning());
|
||||
genObj_->setFixedSlot(GeneratorObject::YIELD_AND_AWAIT_INDEX_SLOT,
|
||||
Int32Value(yieldAwaitIndex_));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Handle leaving a frame with debuggers watching. |frameOk| indicates whether
|
||||
* the frame is exiting normally or abruptly. Set |cx|'s exception and/or
|
||||
|
@ -926,32 +967,11 @@ Debugger::slowPathOnLeaveFrame(JSContext* cx, AbstractFramePtr frame, jsbytecode
|
|||
RootedValue value(cx);
|
||||
Debugger::resultToCompletion(cx, frameOk, frame.returnValue(), &resumeMode, &value);
|
||||
|
||||
// If we are yielding or awaiting, the generator is currently in the
|
||||
// "suspended" state. Letting script observe this state, with the
|
||||
// generator on stack and yet also reenterable, would be bad, so mark
|
||||
// it running while we fire events.
|
||||
int32_t yieldAwaitIndex = 0;
|
||||
// If we are yielding or awaiting, we'll need to mark the generator as
|
||||
// "running" temporarily.
|
||||
Rooted<GeneratorObject*> genObj(cx);
|
||||
if (frame.isFunctionFrame() && (frame.callee()->isGenerator() || frame.callee()->isAsync())) {
|
||||
if (frame.isFunctionFrame() && (frame.callee()->isGenerator() || frame.callee()->isAsync()))
|
||||
genObj = GetGeneratorObjectForFrame(cx, frame);
|
||||
if (genObj) {
|
||||
if (!genObj->isBeforeInitialYield() && !genObj->isClosed() && genObj->isSuspended()) {
|
||||
yieldAwaitIndex =
|
||||
genObj->getFixedSlot(GeneratorObject::YIELD_AND_AWAIT_INDEX_SLOT).toInt32();
|
||||
genObj->setRunning();
|
||||
} else {
|
||||
// We're returning or throwing, not yielding or awaiting. The
|
||||
// generator is already closed, if it was ever exposed at all.
|
||||
genObj = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
auto restoreGenSuspended = MakeScopeExit([&] {
|
||||
if (genObj) {
|
||||
genObj->setFixedSlot(GeneratorObject::YIELD_AND_AWAIT_INDEX_SLOT,
|
||||
Int32Value(yieldAwaitIndex));
|
||||
}
|
||||
});
|
||||
|
||||
// This path can be hit via unwinding the stack due to over-recursion or
|
||||
// OOM. In those cases, don't fire the frames' onPop handlers, because
|
||||
|
@ -982,7 +1002,11 @@ Debugger::slowPathOnLeaveFrame(JSContext* cx, AbstractFramePtr frame, jsbytecode
|
|||
// Call the onPop handler.
|
||||
ResumeMode nextResumeMode = resumeMode;
|
||||
RootedValue nextValue(cx, wrappedValue);
|
||||
bool success = handler->onPop(cx, frameobj, nextResumeMode, &nextValue);
|
||||
bool success;
|
||||
{
|
||||
AutoSetGeneratorRunning asgr(cx, genObj);
|
||||
success = handler->onPop(cx, frameobj, nextResumeMode, &nextValue);
|
||||
}
|
||||
nextResumeMode = dbg->processParsedHandlerResult(ar, frame, pc, success,
|
||||
nextResumeMode, &nextValue);
|
||||
|
||||
|
@ -1476,7 +1500,7 @@ AdjustGeneratorResumptionValue(JSContext* cx, AbstractFramePtr frame,
|
|||
vp.setObject(*pair);
|
||||
|
||||
// 2. The generator must be closed.
|
||||
GeneratorObject::finalSuspend(genObj);
|
||||
genObj->setClosed();
|
||||
} else {
|
||||
// We're before the initial yield. Carry on with the forced return.
|
||||
// The debuggee will see a call to a generator returning the
|
||||
|
|
|
@ -2445,6 +2445,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
JS_FN("_DefineDataProperty", intrinsic_DefineDataProperty, 4,0),
|
||||
JS_FN("_DefineProperty", intrinsic_DefineProperty, 6,0),
|
||||
JS_FN("CopyDataPropertiesOrGetOwnKeys", intrinsic_CopyDataPropertiesOrGetOwnKeys, 3,0),
|
||||
JS_INLINABLE_FN("SameValue", js::obj_is, 2,0, ObjectIs),
|
||||
|
||||
JS_INLINABLE_FN("_IsConstructing", intrinsic_IsConstructing, 0,0,
|
||||
IntrinsicIsConstructing),
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <utility>
|
||||
|
||||
#include "js/AllocPolicy.h"
|
||||
#include "js/CompileOptions.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/Vector.h"
|
||||
|
|
|
@ -515,13 +515,11 @@ nsHttpChannelAuthProvider::PrepareForAuthentication(bool proxyAuth)
|
|||
// We need to remove any Proxy_Authorization header left over from a
|
||||
// non-request based authentication handshake (e.g., for NTLM auth).
|
||||
|
||||
nsAutoCString contractId;
|
||||
contractId.AssignLiteral(NS_HTTP_AUTHENTICATOR_CONTRACTID_PREFIX);
|
||||
contractId.Append(mProxyAuthType);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIHttpAuthenticator> precedingAuth =
|
||||
do_GetService(contractId.get(), &rv);
|
||||
nsCOMPtr<nsIHttpAuthenticator> precedingAuth;
|
||||
nsCString proxyAuthType;
|
||||
rv = GetAuthenticator(mProxyAuthType.get(), proxyAuthType,
|
||||
getter_AddRefs(precedingAuth));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ var bundle;
|
|||
var certArray;
|
||||
/**
|
||||
* The checkbox storing whether the user wants to remember the selected cert.
|
||||
* @type nsIDOMXULCheckboxElement
|
||||
* @type Element checkbox, has to have |checked| property.
|
||||
*/
|
||||
var rememberBox;
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ linux64/opt:
|
|||
tooltool-downloads: public
|
||||
need-xvfb: true
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-rust-size
|
||||
- linux64-cbindgen
|
||||
|
@ -54,8 +54,8 @@ linux64-plain/opt:
|
|||
tooltool-downloads: public
|
||||
run-on-projects: [trunk]
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-node
|
||||
- linux64-cbindgen
|
||||
|
@ -86,8 +86,8 @@ linux64-dmd/opt:
|
|||
need-xvfb: true
|
||||
run-on-projects: []
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-rust-size
|
||||
- linux64-cbindgen
|
||||
|
@ -188,8 +188,8 @@ linux64/debug:
|
|||
tooltool-downloads: public
|
||||
need-xvfb: true
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-cbindgen
|
||||
- linux64-sccache
|
||||
- linux64-rust
|
||||
|
@ -220,8 +220,8 @@ linux64-plain/debug:
|
|||
tooltool-downloads: public
|
||||
run-on-projects: [trunk]
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-node
|
||||
- linux64-cbindgen
|
||||
|
@ -357,8 +357,8 @@ linux/opt:
|
|||
tooltool-downloads: public
|
||||
need-xvfb: true
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-rust-size
|
||||
- linux64-cbindgen
|
||||
|
@ -391,8 +391,8 @@ linux/debug:
|
|||
tooltool-downloads: public
|
||||
need-xvfb: true
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-rust-size
|
||||
- linux64-cbindgen
|
||||
|
@ -464,8 +464,8 @@ linux-rusttests/opt:
|
|||
need-xvfb: true
|
||||
run-on-projects: ['trunk', 'try']
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-cbindgen
|
||||
- linux64-sccache
|
||||
|
@ -500,8 +500,8 @@ linux-rusttests/debug:
|
|||
need-xvfb: true
|
||||
run-on-projects: ['trunk', 'try']
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-cbindgen
|
||||
- linux64-sccache
|
||||
|
@ -614,8 +614,8 @@ linux64-asan/opt:
|
|||
tooltool-downloads: public
|
||||
need-xvfb: true
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-rust-size
|
||||
- linux64-cbindgen
|
||||
|
@ -647,8 +647,8 @@ linux64-asan-fuzzing/opt:
|
|||
tooltool-downloads: public
|
||||
need-xvfb: true
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-rust-size
|
||||
- linux64-cbindgen
|
||||
|
@ -682,8 +682,8 @@ linux64-asan-fuzzing-ccov/opt:
|
|||
tooltool-downloads: public
|
||||
need-xvfb: true
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-rust-size
|
||||
- linux64-cbindgen
|
||||
|
@ -755,8 +755,8 @@ linux64-asan-reporter-nightly/opt:
|
|||
tooltool-downloads: public
|
||||
need-xvfb: true
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-rust-size
|
||||
- linux64-cbindgen
|
||||
|
@ -788,8 +788,8 @@ linux64-asan/debug:
|
|||
tooltool-downloads: public
|
||||
need-xvfb: true
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-rust-size
|
||||
- linux64-cbindgen
|
||||
|
@ -822,8 +822,8 @@ linux64-lto/opt:
|
|||
tooltool-downloads: public
|
||||
need-xvfb: true
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-rust-size
|
||||
- linux64-cbindgen
|
||||
|
@ -856,8 +856,8 @@ linux64-lto/debug:
|
|||
tooltool-downloads: public
|
||||
need-xvfb: true
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-rust-size
|
||||
- linux64-cbindgen
|
||||
|
@ -929,8 +929,8 @@ linux64-noopt/debug:
|
|||
need-xvfb: true
|
||||
run-on-projects: ['trunk', 'try']
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-rust-size
|
||||
- linux64-cbindgen
|
||||
|
@ -965,8 +965,8 @@ linux64-rusttests/opt:
|
|||
need-xvfb: true
|
||||
run-on-projects: ['trunk', 'try']
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-cbindgen
|
||||
- linux64-sccache
|
||||
|
@ -1000,8 +1000,8 @@ linux64-rusttests/debug:
|
|||
need-xvfb: true
|
||||
run-on-projects: ['trunk', 'try']
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-cbindgen
|
||||
- linux64-sccache
|
||||
|
@ -1033,8 +1033,8 @@ linux64-tup/opt:
|
|||
tooltool-downloads: public
|
||||
need-xvfb: true
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust-nightly
|
||||
- linux64-cbindgen
|
||||
- linux64-sccache
|
||||
|
@ -1065,8 +1065,8 @@ linux64-jsdcov/opt:
|
|||
tooltool-downloads: public
|
||||
need-xvfb: true
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-cbindgen
|
||||
- linux64-sccache
|
||||
|
@ -1165,8 +1165,8 @@ linux64-add-on-devel/opt:
|
|||
need-xvfb: true
|
||||
run-on-projects: ['mozilla-beta', 'mozilla-release', 'mozilla-esr45']
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-rust-size
|
||||
- linux64-cbindgen
|
||||
|
|
|
@ -54,6 +54,10 @@ crashtest:
|
|||
by-test-platform:
|
||||
linux32/debug: both
|
||||
default: true
|
||||
max-run-time:
|
||||
by-test-platform:
|
||||
android-em.*: 7200
|
||||
default: 3600
|
||||
|
||||
jsreftest:
|
||||
description: "JS Reftest run"
|
||||
|
|
|
@ -306,6 +306,9 @@ linux64-binutils:
|
|||
resources:
|
||||
- 'build/unix/build-binutils/build-binutils.sh'
|
||||
toolchain-artifact: public/build/binutils.tar.xz
|
||||
fetches:
|
||||
fetch:
|
||||
- binutils-2.28.1
|
||||
|
||||
linux64-cctools-port:
|
||||
description: "cctools-port toolchain build"
|
||||
|
|
|
@ -43,8 +43,8 @@ jobs:
|
|||
tooltool-downloads: public
|
||||
need-xvfb: true
|
||||
toolchains:
|
||||
- linux64-binutils
|
||||
- linux64-clang
|
||||
- linux64-gcc
|
||||
- linux64-rust
|
||||
- linux64-cbindgen
|
||||
- linux64-sccache
|
||||
|
|
|
@ -189,6 +189,7 @@ var BrowserTestUtils = {
|
|||
// If DEFAULT_PROCESSSELECTOR_CID is null, we're in non-e10s mode and we
|
||||
// should skip this.
|
||||
if (options.forceNewProcess && DEFAULT_PROCESSSELECTOR_CID) {
|
||||
Services.ppmm.releaseCachedProcesses();
|
||||
registrar.registerFactory(OUR_PROCESSSELECTOR_CID, "",
|
||||
PROCESSSELECTOR_CONTRACTID, null);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ config = {
|
|||
'install',
|
||||
'run-tests',
|
||||
],
|
||||
"tooltool_cache": "/builds/worker/tooltool_cache",
|
||||
"tooltool_cache": os.environ.get("TOOLTOOL_CACHE"),
|
||||
"tooltool_servers": ['http://relengapi/tooltool/'],
|
||||
"hostutils_manifest_path": "testing/config/tooltool-manifests/linux64/hostutils.manifest",
|
||||
"avds_dir": "/builds/worker/workspace/build/.android",
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"fb51f35c4be7c1a6768ab026c11092cbf8b81aebaaa970e19f0b0033f7a26b88","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"d9771b8c6cf4426d3846de54c1febe20907f1eeadf7adfb5ade89a83bd9ea77f","src/expr.rs":"dc3e299b02b33e1441d6e82482409272554cfae8f271e3b5664a216ecf1fecdc","src/lib.rs":"a37cca356d761557bd27e08ce46044b758bd21d523d039105e71597f64da9ba1","src/literal.rs":"deddad795a6788a78533f49b6afa784702e2dbfd9848d6fad60ec5cecabfb840","src/token.rs":"85d63f778a438ba9f39dac643473d457103bad2f2d4b53dd62e65ded65b1a83d","tests/clang.rs":"125058defb8166679019475d72a76804ac2dbfc09f50c3fad5b908970d652f02","tests/input/chars.h":"69c8141870872b795b5174bad125b748732c2b01d0e98ffcfc37b19f3f791f69","tests/input/fail.h":"b0b6cffd2dd17410b5eb02ee79ab75754820480b960db8a9866cc9983bd36b65","tests/input/floats.h":"28ec664e793c494e1a31f3bc5b790014e9921fc741bf475a86319b9a9eee5915","tests/input/int_signed.h":"934199eded85dd7820ca08c0beb1381ee6d9339970d2720a69c23025571707ce","tests/input/int_unsigned.h":"3cdf9782a6e74796833ea0dfcb35b6ab6ca76a89080e82ed39bac0d55064d88c","tests/input/strings.h":"27de768b506a1aedfdb750ac53b7a395cc20395958ff3263af1ab5851e2c412c"},"package":"393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"}
|
||||
{"files":{"Cargo.toml":"22914a43154e0b38bbe265a67024c1f98af9087ca561448ac0f13ed57c9311ae","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"d9771b8c6cf4426d3846de54c1febe20907f1eeadf7adfb5ade89a83bd9ea77f","src/expr.rs":"b888963ab9eb344c93c0654286231b4204809a971682155fade5c69a4493636f","src/lib.rs":"78bbde89e803cf931216e38bdd992e13894cd898868478a258eac5155bdf4de9","src/literal.rs":"fb80a7b43d96bedfd47bc2d39eaf588c5cef6a2374132fbdfe5146dd56a1894c","src/token.rs":"52d42deb2a2575bb8631e2e821593d8288fed16e21bab3ceeacb6a7b06c40087","tests/clang.rs":"a650cde69ab2e801f994f15e4cb32c538e53abefcdd862865ce277ce9a055242","tests/input/chars.h":"69c8141870872b795b5174bad125b748732c2b01d0e98ffcfc37b19f3f791f69","tests/input/fail.h":"b0b6cffd2dd17410b5eb02ee79ab75754820480b960db8a9866cc9983bd36b65","tests/input/floats.h":"28ec664e793c494e1a31f3bc5b790014e9921fc741bf475a86319b9a9eee5915","tests/input/int_signed.h":"934199eded85dd7820ca08c0beb1381ee6d9339970d2720a69c23025571707ce","tests/input/int_unsigned.h":"f47c1ccb6c69856162639277d7552090055420155df55f65581e57217cccce76","tests/input/strings.h":"75c60527068172b97983d2b8361938e856ea394002d5bef05de1adc6a0f5fc01","tests/input/test_llvm_bug_9069.h":"8d9ae1d1eadc8f6d5c14296f984547fe894d0f2ce5cd6d7aa8caad40a56bc5e1"},"package":"42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c"}
|
|
@ -1,15 +1,26 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g. crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
name = "cexpr"
|
||||
version = "0.2.0"
|
||||
version = "0.2.3"
|
||||
authors = ["Jethro Beekman <jethro@jbeekman.nl>"]
|
||||
license = "Apache-2.0/MIT"
|
||||
description = "A C expression parser and evaluator"
|
||||
documentation = "https://jethrogb.github.io/rust-cexpr/cexpr"
|
||||
documentation = "https://docs.rs/cexpr/"
|
||||
keywords = ["C", "expression", "parser"]
|
||||
license = "Apache-2.0/MIT"
|
||||
repository = "https://github.com/jethrogb/rust-cexpr"
|
||||
keywords = ["C","expression","parser"]
|
||||
|
||||
[dependencies]
|
||||
nom = "^1"
|
||||
|
||||
[dev-dependencies]
|
||||
clang-sys = "0.11.0"
|
||||
[dependencies.nom]
|
||||
version = "^3"
|
||||
features = ["verbose-errors"]
|
||||
[dev-dependencies.clang-sys]
|
||||
version = "0.11.0"
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
//!
|
||||
//! The `sizeof` operator is not supported.
|
||||
//!
|
||||
//! String concatenation is supported, but width prefixes are ignored all
|
||||
//! String concatenation is supported, but width prefixes are ignored; all
|
||||
//! strings are treated as narrow strings.
|
||||
//!
|
||||
//! Use the `IdentifierParser` to substitute identifiers found in expressions.
|
||||
|
@ -85,9 +85,9 @@ impl From<Vec<u8>> for EvalResult {
|
|||
// ===========================================
|
||||
|
||||
macro_rules! exact_token (
|
||||
($i:expr, $k: ident, $c: expr) => ({
|
||||
($i:expr, $k:ident, $c:expr) => ({
|
||||
if $i.is_empty() {
|
||||
let res: CResult<&[u8]> = IResult::Incomplete(Needed::Size(1));
|
||||
let res: CResult<&[u8]> = IResult::Incomplete(Needed::Size($c.len()));
|
||||
res
|
||||
} else {
|
||||
if $i[0].kind==TokenKind::$k && &$i[0].raw[..]==$c {
|
||||
|
@ -100,7 +100,7 @@ macro_rules! exact_token (
|
|||
);
|
||||
|
||||
macro_rules! typed_token (
|
||||
($i:expr, $k: ident) => ({
|
||||
($i:expr, $k:ident) => ({
|
||||
if $i.is_empty() {
|
||||
let res: CResult<&[u8]> = IResult::Incomplete(Needed::Size(1));
|
||||
res
|
||||
|
@ -114,6 +114,7 @@ macro_rules! typed_token (
|
|||
});
|
||||
);
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! any_token (
|
||||
($i:expr,) => ({
|
||||
if $i.is_empty() {
|
||||
|
@ -126,7 +127,24 @@ macro_rules! any_token (
|
|||
);
|
||||
|
||||
macro_rules! p (
|
||||
($i:expr, $c: expr) => (exact_token!($i,Punctuation,$c.as_bytes()))
|
||||
($i:expr, $c:expr) => (exact_token!($i,Punctuation,$c.as_bytes()))
|
||||
);
|
||||
|
||||
macro_rules! one_of_punctuation (
|
||||
($i:expr, $c:expr) => ({
|
||||
if $i.is_empty() {
|
||||
let min = $c.iter().map(|opt|opt.len()).min().expect("at least one option");
|
||||
let res: CResult<&[u8]> = IResult::Incomplete(Needed::Size(min));
|
||||
res
|
||||
} else {
|
||||
if $i[0].kind==TokenKind::Punctuation && $c.iter().any(|opt|opt.as_bytes()==&$i[0].raw[..]) {
|
||||
IResult::Done(&$i[1..], &$i[0].raw[..])
|
||||
} else {
|
||||
const VAILD_VALUES: &'static [&'static str] = &$c;
|
||||
IResult::Error(Err::Position(ErrorKind::Custom(::Error::ExactTokens(TokenKind::Punctuation,VAILD_VALUES)), $i))
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
// ==================================================
|
||||
|
@ -264,71 +282,104 @@ impl<'a> PRef<'a> {
|
|||
delimited!(p!("("),call_m!(self.numeric_expr),p!(")")) |
|
||||
numeric!(call_m!(self.literal)) |
|
||||
numeric!(call_m!(self.identifier)) |
|
||||
map_opt!(pair!(alt!( p!("+") | p!("-") | p!("~") ),call_m!(self.unary)),unary_op)
|
||||
map_opt!(pair!(one_of_punctuation!(["+", "-", "~"]),call_m!(self.unary)),unary_op)
|
||||
)
|
||||
);
|
||||
|
||||
method!(mul_div_rem<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
|
||||
chain!(
|
||||
mut acc: call_m!(self.unary) ~
|
||||
many0!(alt!(
|
||||
tap!(mul: preceded!(p!("*"), call_m!(self.unary)) => acc *= &mul) |
|
||||
tap!(div: preceded!(p!("/"), call_m!(self.unary)) => acc /= &div) |
|
||||
tap!(rem: preceded!(p!("%"), call_m!(self.unary)) => acc %= &rem)
|
||||
)),
|
||||
|| { return acc }
|
||||
do_parse!(
|
||||
acc: call_m!(self.unary) >>
|
||||
res: fold_many0!(
|
||||
pair!(one_of_punctuation!(["*", "/", "%"]), call_m!(self.unary)),
|
||||
acc,
|
||||
|mut acc, (op, val): (&[u8], EvalResult)| {
|
||||
match op[0] as char {
|
||||
'*' => acc *= &val,
|
||||
'/' => acc /= &val,
|
||||
'%' => acc %= &val,
|
||||
_ => unreachable!()
|
||||
};
|
||||
acc
|
||||
}
|
||||
) >> (res)
|
||||
)
|
||||
);
|
||||
|
||||
method!(add_sub<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
|
||||
chain!(
|
||||
mut acc: call_m!(self.mul_div_rem) ~
|
||||
many0!(alt!(
|
||||
tap!(add: preceded!(p!("+"), call_m!(self.mul_div_rem)) => acc += &add) |
|
||||
tap!(sub: preceded!(p!("-"), call_m!(self.mul_div_rem)) => acc -= &sub)
|
||||
)),
|
||||
|| { return acc }
|
||||
do_parse!(
|
||||
acc: call_m!(self.mul_div_rem) >>
|
||||
res: fold_many0!(
|
||||
pair!(one_of_punctuation!(["+", "-"]), call_m!(self.mul_div_rem)),
|
||||
acc,
|
||||
|mut acc, (op, val): (&[u8], EvalResult)| {
|
||||
match op[0] as char {
|
||||
'+' => acc += &val,
|
||||
'-' => acc -= &val,
|
||||
_ => unreachable!()
|
||||
};
|
||||
acc
|
||||
}
|
||||
) >> (res)
|
||||
)
|
||||
);
|
||||
|
||||
method!(shl_shr<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
|
||||
numeric!(chain!(
|
||||
mut acc: call_m!(self.add_sub) ~
|
||||
many0!(alt!(
|
||||
tap!(shl: preceded!(p!("<<"), call_m!(self.add_sub)) => acc <<= &shl) |
|
||||
tap!(shr: preceded!(p!(">>"), call_m!(self.add_sub)) => acc >>= &shr)
|
||||
)),
|
||||
|| { return acc }
|
||||
numeric!(do_parse!(
|
||||
acc: call_m!(self.add_sub) >>
|
||||
res: fold_many0!(
|
||||
pair!(one_of_punctuation!(["<<", ">>"]), call_m!(self.add_sub)),
|
||||
acc,
|
||||
|mut acc, (op, val): (&[u8], EvalResult)| {
|
||||
match op {
|
||||
b"<<" => acc <<= &val,
|
||||
b">>" => acc >>= &val,
|
||||
_ => unreachable!()
|
||||
};
|
||||
acc
|
||||
}
|
||||
) >> (res)
|
||||
))
|
||||
);
|
||||
|
||||
method!(and<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
|
||||
numeric!(chain!(
|
||||
mut acc: call_m!(self.shl_shr) ~
|
||||
many0!(
|
||||
tap!(and: preceded!(p!("&"), call_m!(self.shl_shr)) => acc &= &and)
|
||||
),
|
||||
|| { return acc }
|
||||
numeric!(do_parse!(
|
||||
acc: call_m!(self.shl_shr) >>
|
||||
res: fold_many0!(
|
||||
preceded!(p!("&"), call_m!(self.shl_shr)),
|
||||
acc,
|
||||
|mut acc, val: EvalResult| {
|
||||
acc &= &val;
|
||||
acc
|
||||
}
|
||||
) >> (res)
|
||||
))
|
||||
);
|
||||
|
||||
method!(xor<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
|
||||
numeric!(chain!(
|
||||
mut acc: call_m!(self.and) ~
|
||||
many0!(
|
||||
tap!(xor: preceded!(p!("^"), call_m!(self.and)) => acc ^= &xor)
|
||||
),
|
||||
|| { return acc }
|
||||
numeric!(do_parse!(
|
||||
acc: call_m!(self.and) >>
|
||||
res: fold_many0!(
|
||||
preceded!(p!("^"), call_m!(self.and)),
|
||||
acc,
|
||||
|mut acc, val: EvalResult| {
|
||||
acc ^= &val;
|
||||
acc
|
||||
}
|
||||
) >> (res)
|
||||
))
|
||||
);
|
||||
|
||||
method!(or<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
|
||||
numeric!(chain!(
|
||||
mut acc: call_m!(self.xor) ~
|
||||
many0!(
|
||||
tap!(or: preceded!(p!("|"), call_m!(self.xor)) => acc |= &or)
|
||||
),
|
||||
|| { return acc }
|
||||
numeric!(do_parse!(
|
||||
acc: call_m!(self.xor) >>
|
||||
res: fold_many0!(
|
||||
preceded!(p!("|"), call_m!(self.xor)),
|
||||
acc,
|
||||
|mut acc, val: EvalResult| {
|
||||
acc |= &val;
|
||||
acc
|
||||
}
|
||||
) >> (res)
|
||||
))
|
||||
);
|
||||
|
||||
|
@ -390,8 +441,8 @@ impl<'a> PRef<'a> {
|
|||
|
||||
method!(expr<PRef<'a>,&[Token],EvalResult,::Error>, mut self,
|
||||
alt!(
|
||||
delimited!(p!("("),call_m!(self.expr),p!(")")) |
|
||||
call_m!(self.numeric_expr) |
|
||||
delimited!(p!("("),call_m!(self.expr),p!(")")) |
|
||||
call_m!(self.concat_str) |
|
||||
call_m!(self.literal) |
|
||||
call_m!(self.identifier)
|
||||
|
@ -474,3 +525,54 @@ pub fn expr<'a>(input: &'a [Token]) -> CResult<'a,EvalResult> {
|
|||
pub fn macro_definition<'a>(input: &'a [Token]) -> CResult<'a,(&'a [u8],EvalResult)> {
|
||||
IdentifierParser::new(&HashMap::new()).macro_definition(input)
|
||||
}
|
||||
|
||||
named_attr!(
|
||||
/// Parse a functional macro declaration from a list of tokens.
|
||||
///
|
||||
/// Returns the identifier for the macro and the argument list (in order). The
|
||||
/// input should not include `#define`. The actual definition is not parsed and
|
||||
/// may be obtained from the unparsed data returned.
|
||||
///
|
||||
/// Returns an error if the input is not a functional macro or if the token
|
||||
/// stream contains comments.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use cexpr::expr::{IdentifierParser, EvalResult, fn_macro_declaration};
|
||||
/// use cexpr::assert_full_parse;
|
||||
/// use cexpr::token::Kind::*;
|
||||
/// use cexpr::token::Token;
|
||||
///
|
||||
/// // #define SUFFIX(arg) arg "suffix"
|
||||
/// let tokens = vec![
|
||||
/// (Identifier, &b"SUFFIX"[..]).into(),
|
||||
/// (Punctuation, &b"("[..]).into(),
|
||||
/// (Identifier, &b"arg"[..]).into(),
|
||||
/// (Punctuation, &b")"[..]).into(),
|
||||
/// (Identifier, &b"arg"[..]).into(),
|
||||
/// (Literal, &br#""suffix""#[..]).into(),
|
||||
/// ];
|
||||
///
|
||||
/// // Try to parse the functional part
|
||||
/// let (expr, (ident, args)) = fn_macro_declaration(&tokens).unwrap();
|
||||
/// assert_eq!(ident, b"SUFFIX");
|
||||
///
|
||||
/// // Create dummy arguments
|
||||
/// let idents = args.into_iter().map(|arg|
|
||||
/// (arg.to_owned(), EvalResult::Str(b"test".to_vec()))
|
||||
/// ).collect();
|
||||
///
|
||||
/// // Evaluate the macro
|
||||
/// let (_, evaluated) = assert_full_parse(IdentifierParser::new(&idents).expr(expr)).unwrap();
|
||||
/// assert_eq!(evaluated, EvalResult::Str(b"testsuffix".to_vec()));
|
||||
/// ```
|
||||
,pub fn_macro_declaration<&[Token],(&[u8],Vec<&[u8]>),::Error>,
|
||||
pair!(
|
||||
typed_token!(Identifier),
|
||||
delimited!(
|
||||
p!("("),
|
||||
separated_list!(p!(","), typed_token!(Identifier)),
|
||||
p!(")")
|
||||
)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -24,6 +24,8 @@ use nom::*;
|
|||
pub enum Error {
|
||||
/// Expected the specified token
|
||||
ExactToken(token::Kind,&'static [u8]),
|
||||
/// Expected one of the specified tokens
|
||||
ExactTokens(token::Kind,&'static [&'static str]),
|
||||
/// Expected a token of the specified kind
|
||||
TypedToken(token::Kind),
|
||||
/// An unknown identifier was encountered
|
||||
|
|
|
@ -83,34 +83,6 @@ impl Into<Vec<u8>> for CChar {
|
|||
// ======== macros that shouldn't be necessary ========
|
||||
// ====================================================
|
||||
|
||||
fn split_off_prefix<'a,T>(full: &'a [T], suffix: &'a [T]) -> &'a [T] {
|
||||
let n=::std::mem::size_of::<T>();
|
||||
let start=full.as_ptr() as usize;
|
||||
let end=start+(full.len()*n);
|
||||
let cur=suffix.as_ptr() as usize;
|
||||
assert!(start<=cur && cur<=end);
|
||||
&full[..(cur-start)/n]
|
||||
}
|
||||
|
||||
// There is a HORRIBLE BUG in nom's recognize!
|
||||
// https://github.com/Geal/nom/issues/278
|
||||
#[macro_export]
|
||||
macro_rules! my_recognize (
|
||||
($i:expr, $submac:ident!( $($args:tt)* )) => (
|
||||
{
|
||||
match $submac!($i, $($args)*) {
|
||||
IResult::Done(i,_) => IResult::Done(i, split_off_prefix($i,i)),
|
||||
IResult::Error(e) => IResult::Error(e),
|
||||
IResult::Incomplete(i) => IResult::Incomplete(i)
|
||||
}
|
||||
}
|
||||
);
|
||||
($i:expr, $f:expr) => (
|
||||
my_recognize!($i, call!($f))
|
||||
);
|
||||
);
|
||||
|
||||
|
||||
macro_rules! force_type (
|
||||
($input:expr,IResult<$i:ty,$o:ty,$e:ty>) => (IResult::Error::<$i,$o,$e>(Err::Position(ErrorKind::Fix,$input)))
|
||||
);
|
||||
|
@ -171,8 +143,8 @@ fn c_unicode_escape(n: Vec<u8>) -> Option<CChar> {
|
|||
|
||||
named!(escaped_char<CChar>,
|
||||
preceded!(char!('\\'),alt!(
|
||||
map!(one_of!(br#"'"?\"#),CChar::Char) |
|
||||
map!(one_of!(b"abfnrtv"),escape2char) |
|
||||
map!(one_of!(r#"'"?\"#),CChar::Char) |
|
||||
map!(one_of!("abfnrtv"),escape2char) |
|
||||
map_opt!(many_m_n!(1,3,octal),|v|c_raw_escape(v,8)) |
|
||||
map_opt!(preceded!(char!('x'),many1!(hexadecimal)),|v|c_raw_escape(v,16)) |
|
||||
map_opt!(preceded!(char!('u'),many_m_n!(4,4,hexadecimal)),c_unicode_escape) |
|
||||
|
@ -200,13 +172,10 @@ named!(c_char<CChar>,
|
|||
named!(c_string<Vec<u8> >,
|
||||
delimited!(
|
||||
alt!( preceded!(c_width_prefix,char!('"')) | char!('"') ),
|
||||
chain!(
|
||||
mut vec: value!(vec![]) ~
|
||||
many0!(alt!(
|
||||
map!(tap!(c: escaped_char => { let v: Vec<u8>=c.into(); vec.extend_from_slice(&v) } ),|_|()) |
|
||||
map!(tap!(s: is_not!(b"\"") => vec.extend_from_slice(s) ),|_|())
|
||||
)),
|
||||
||{return vec}
|
||||
fold_many0!(
|
||||
alt!(map!(escaped_char, |c:CChar| c.into()) | map!(is_not!("\""), |c: &[u8]| c.into())),
|
||||
Vec::new(),
|
||||
|mut v: Vec<u8>, res:Vec<u8>| { v.extend_from_slice(&res); v }
|
||||
),
|
||||
char!('"')
|
||||
)
|
||||
|
@ -240,11 +209,11 @@ named!(float_exp<(Option<u8>,Vec<u8>)>,preceded!(byte!(b'e'|b'E'),pair!(opt!(byt
|
|||
|
||||
named!(c_float<f64>,
|
||||
map_opt!(alt!(
|
||||
terminated!(my_recognize!(tuple!(many1!(decimal),byte!(b'.'),many0!(decimal))),opt!(float_width)) |
|
||||
terminated!(my_recognize!(tuple!(many0!(decimal),byte!(b'.'),many1!(decimal))),opt!(float_width)) |
|
||||
terminated!(my_recognize!(tuple!(many0!(decimal),opt!(byte!(b'.')),many1!(decimal),float_exp)),opt!(float_width)) |
|
||||
terminated!(my_recognize!(tuple!(many1!(decimal),opt!(byte!(b'.')),many0!(decimal),float_exp)),opt!(float_width)) |
|
||||
terminated!(my_recognize!(many1!(decimal)),float_width)
|
||||
terminated!(recognize!(tuple!(many1!(decimal),byte!(b'.'),many0!(decimal))),opt!(float_width)) |
|
||||
terminated!(recognize!(tuple!(many0!(decimal),byte!(b'.'),many1!(decimal))),opt!(float_width)) |
|
||||
terminated!(recognize!(tuple!(many0!(decimal),opt!(byte!(b'.')),many1!(decimal),float_exp)),opt!(float_width)) |
|
||||
terminated!(recognize!(tuple!(many1!(decimal),opt!(byte!(b'.')),many0!(decimal),float_exp)),opt!(float_width)) |
|
||||
terminated!(recognize!(many1!(decimal)),float_width)
|
||||
),|v|str::from_utf8(v).ok().and_then(|i|f64::from_str(i).ok()))
|
||||
);
|
||||
|
||||
|
|
|
@ -24,6 +24,15 @@ pub struct Token {
|
|||
pub raw: Box<[u8]>,
|
||||
}
|
||||
|
||||
impl<'a> From<(Kind, &'a [u8])> for Token {
|
||||
fn from((kind, value): (Kind, &'a [u8])) -> Token {
|
||||
Token {
|
||||
kind: kind,
|
||||
raw: value.to_owned().into_boxed_slice()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove all comment tokens from a vector of tokens
|
||||
pub fn remove_comments(v: &mut Vec<Token>) -> &mut Vec<Token> {
|
||||
v.retain(|t|t.kind!=Kind::Comment);
|
||||
|
|
|
@ -14,25 +14,45 @@ use std::collections::HashMap;
|
|||
|
||||
use clang_sys::*;
|
||||
use cexpr::token::Token;
|
||||
use cexpr::expr::{IdentifierParser,EvalResult};
|
||||
use cexpr::expr::{IdentifierParser,EvalResult,fn_macro_declaration};
|
||||
use cexpr::literal::CChar;
|
||||
use cexpr::assert_full_parse;
|
||||
|
||||
// main testing routine
|
||||
fn test_definition(ident: Vec<u8>, tokens: &[Token], idents: &mut HashMap<Vec<u8>,EvalResult>) -> bool {
|
||||
fn bytes_to_int(value: &[u8]) -> Option<EvalResult> {
|
||||
str::from_utf8(value).ok()
|
||||
.map(|s|s.replace("n","-"))
|
||||
.map(|s|s.replace("_",""))
|
||||
.and_then(|v|i64::from_str(&v).ok())
|
||||
.map(::std::num::Wrapping)
|
||||
.map(Int)
|
||||
}
|
||||
|
||||
use cexpr::expr::EvalResult::*;
|
||||
|
||||
let display_name=String::from_utf8_lossy(&ident).into_owned();
|
||||
|
||||
let functional;
|
||||
let test={
|
||||
// Split name such as Str_test_string into (Str,test_string)
|
||||
let pos=ident.iter().position(|c|*c==b'_').expect(&format!("Invalid definition in testcase: {}",display_name));
|
||||
let expected=&ident[..pos];
|
||||
let value=&ident[(pos+1)..];
|
||||
let mut expected=&ident[..pos];
|
||||
let mut value=&ident[(pos+1)..];
|
||||
|
||||
functional=expected==b"Fn";
|
||||
|
||||
if functional {
|
||||
let ident=value;
|
||||
let pos=ident.iter().position(|c|*c==b'_').expect(&format!("Invalid definition in testcase: {}",display_name));
|
||||
expected=&ident[..pos];
|
||||
value=&ident[(pos+1)..];
|
||||
}
|
||||
|
||||
if expected==b"Str" {
|
||||
Some(Str(value.to_owned()))
|
||||
} else if expected==b"Int" {
|
||||
str::from_utf8(value).ok().map(|s|s.replace("n","-")).and_then(|v|i64::from_str(&v).ok()).map(::std::num::Wrapping).map(Int)
|
||||
bytes_to_int(value)
|
||||
} else if expected==b"Float" {
|
||||
str::from_utf8(value).ok().map(|s|s.replace("n","-").replace("p",".")).and_then(|v|f64::from_str(&v).ok()).map(Float)
|
||||
} else if expected==b"CharRaw" {
|
||||
|
@ -44,8 +64,34 @@ fn test_definition(ident: Vec<u8>, tokens: &[Token], idents: &mut HashMap<Vec<u8
|
|||
}.expect(&format!("Invalid definition in testcase: {}",display_name))
|
||||
};
|
||||
|
||||
match IdentifierParser::new(idents).macro_definition(&tokens) {
|
||||
cexpr::nom::IResult::Done(_,(_,val)) => {
|
||||
let result = if functional {
|
||||
let mut fnidents;
|
||||
let expr_tokens;
|
||||
match fn_macro_declaration(&tokens) {
|
||||
cexpr::nom::IResult::Done(rest,(_,args)) => {
|
||||
fnidents=idents.clone();
|
||||
expr_tokens=rest;
|
||||
for arg in args {
|
||||
let val = match test {
|
||||
Int(_) => bytes_to_int(&arg),
|
||||
Str(_) => Some(Str(arg.to_owned())),
|
||||
_ => unimplemented!()
|
||||
}.expect(&format!("Invalid argument in functional macro testcase: {}",display_name));
|
||||
fnidents.insert(arg.to_owned(), val);
|
||||
}
|
||||
},
|
||||
e => {
|
||||
println!("Failed test for {}, unable to parse functional macro declaration: {:?}",display_name,e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
assert_full_parse(IdentifierParser::new(&fnidents).expr(&expr_tokens))
|
||||
} else {
|
||||
IdentifierParser::new(idents).macro_definition(&tokens).map(|(_,val)|val)
|
||||
};
|
||||
|
||||
match result {
|
||||
cexpr::nom::IResult::Done(_,val) => {
|
||||
if val==test {
|
||||
if let Some(_)=idents.insert(ident,val) {
|
||||
panic!("Duplicate definition for testcase: {}",display_name);
|
||||
|
@ -56,7 +102,7 @@ fn test_definition(ident: Vec<u8>, tokens: &[Token], idents: &mut HashMap<Vec<u8
|
|||
false
|
||||
}
|
||||
},
|
||||
e @ _ => {
|
||||
e => {
|
||||
if test==Invalid {
|
||||
true
|
||||
} else {
|
||||
|
@ -110,9 +156,9 @@ unsafe fn location_in_scope(r: CXSourceRange) -> bool {
|
|||
&& file.0!=ptr::null_mut()
|
||||
}
|
||||
|
||||
fn test_file(file: &str) -> bool {
|
||||
let mut idents=HashMap::new();
|
||||
let mut all_succeeded=true;
|
||||
/// tokenize_range_adjust can be used to work around LLVM bug 9069
|
||||
/// https://bugs.llvm.org//show_bug.cgi?id=9069
|
||||
fn file_visit_macros<F: FnMut(Vec<u8>, Vec<Token>)>(file: &str, tokenize_range_adjust: bool, mut visitor: F) {
|
||||
unsafe {
|
||||
let tu={
|
||||
let index=clang_createIndex(true as _, false as _);
|
||||
|
@ -132,7 +178,7 @@ fn test_file(file: &str) -> bool {
|
|||
if cur.kind==CXCursor_MacroDefinition {
|
||||
let mut range=clang_getCursorExtent(cur);
|
||||
if !location_in_scope(range) { return CXChildVisit_Continue }
|
||||
range.end_int_data-=1; // clang bug for macros only
|
||||
range.end_int_data-=if tokenize_range_adjust { 1 } else { 0 };
|
||||
let mut token_ptr=ptr::null_mut();
|
||||
let mut num=0;
|
||||
clang_tokenize(tu,range,&mut token_ptr,&mut num);
|
||||
|
@ -146,16 +192,44 @@ fn test_file(file: &str) -> bool {
|
|||
}
|
||||
).collect();
|
||||
clang_disposeTokens(tu,token_ptr,num);
|
||||
all_succeeded&=test_definition(clang_str_to_vec(clang_getCursorSpelling(cur)),&tokens,&mut idents);
|
||||
visitor(clang_str_to_vec(clang_getCursorSpelling(cur)),tokens)
|
||||
}
|
||||
}
|
||||
CXChildVisit_Continue
|
||||
});
|
||||
clang_disposeTranslationUnit(tu);
|
||||
};
|
||||
}
|
||||
|
||||
fn test_file(file: &str) -> bool {
|
||||
let mut idents=HashMap::new();
|
||||
let mut all_succeeded=true;
|
||||
file_visit_macros(file, fix_bug_9069(), |ident, tokens| all_succeeded&=test_definition(ident, &tokens, &mut idents));
|
||||
all_succeeded
|
||||
}
|
||||
|
||||
fn fix_bug_9069() -> bool {
|
||||
fn check_bug_9069() -> bool {
|
||||
let mut token_sets = vec![];
|
||||
file_visit_macros("tests/input/test_llvm_bug_9069.h", false, |ident, tokens| {
|
||||
assert_eq!(&ident, b"A");
|
||||
token_sets.push(tokens);
|
||||
});
|
||||
assert_eq!(token_sets.len(), 2);
|
||||
token_sets[0] != token_sets[1]
|
||||
}
|
||||
|
||||
use std::sync::{Once, ONCE_INIT};
|
||||
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
|
||||
|
||||
static CHECK_FIX: Once = ONCE_INIT;
|
||||
static FIX: AtomicBool = ATOMIC_BOOL_INIT;
|
||||
|
||||
CHECK_FIX.call_once(|| FIX.store(check_bug_9069(), Ordering::SeqCst));
|
||||
|
||||
FIX.load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
macro_rules! test_file {
|
||||
($f:ident) => {
|
||||
#[test] fn $f() {
|
||||
|
|
|
@ -10,5 +10,17 @@
|
|||
#define Int_16 (((1)<<4ULL))/*comment*/
|
||||
#define Int_13 1|8^6&2<<1
|
||||
|
||||
#define Int_47 32|15
|
||||
#define Int_38 (32|15)^9
|
||||
#define Int_6 ((32|15)^9)&7
|
||||
#define Int_12 (((32|15)^9)&7)<<1
|
||||
#define Int_17 ((((32|15)^9)&7)<<1)+5
|
||||
#define Int_15 (((((32|15)^9)&7)<<1)+5)-2
|
||||
#define Int_60 ((((((32|15)^9)&7)<<1)+5)-2)*4
|
||||
#define Int_30 (((((((32|15)^9)&7)<<1)+5)-2)*4)/2
|
||||
#define Int_39 32|15^9&7<<1+5-2*4/2
|
||||
|
||||
#define Int_n1 18446744073709551615 /*2^64-1*/
|
||||
#define Int_n9223372036854775808 9223372036854775808
|
||||
|
||||
#define Fn_Int_9(_3) _3*3
|
||||
|
|
|
@ -5,3 +5,8 @@
|
|||
#define Str_concat u"con" L"cat"
|
||||
#define Str_concat_parens ("concat" U"_parens")
|
||||
#define Str_concat_identifier (Str_concat L"_identifier")
|
||||
#define Fn_Str_no_args() "no_args"
|
||||
#define Fn_Str_no_args_concat() "no_args_" Str_concat
|
||||
#define Fn_Str_prepend_arg(arg) "prepend_" arg
|
||||
#define Fn_Str_two_args(two, args) two "_" args
|
||||
#define Fn_Str_three_args(three, _, args) three _ args
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
// The following two definitions should yield the same list of tokens.
|
||||
// If https://bugs.llvm.org//show_bug.cgi?id=9069 is not fixed, they don't.
|
||||
#define A 1
|
||||
#define A 1
|
|
@ -1 +0,0 @@
|
|||
{"files":{".travis.yml":"6d4e81838b10c5e330749857c72c2f2b1a2e575e71abcd11c094f3b612347b2a","CHANGELOG.md":"d4722e028b2a5b88c466b0d759e463b90bdcfa1b79181a1c76cd313b0a27c615","Cargo.toml":"aebcb999933c3425db85012bea19f9ce78da8e7834dbab54d4a2966e8bc62149","LICENSE":"de730187d5563a81342a3c011d968f78dff37c934fac9b3701e8c762b6118a55","src/bits.rs":"97c9148f63e175489bb6199d039c594ddc56bdf0b7491b9f38b8d74e898bca80","src/bytes.rs":"8f29b976a5e8e6500eb618a9dead7f212688ba9eb06c7066a4016e2db99fed00","src/character.rs":"9ee081f56b508212231ff70d7455b1b85ae44722a39aa60223e8cd95c6570859","src/internal.rs":"ada499b9c178be2a7f9b56319ffb10a778f25fafcda39c78d26b364d89debd72","src/lib.rs":"34efb051214acfde2053e93a7ba718a4fd41b6e0d9edd65a1737605d99b994ab","src/macros.rs":"d39ce3a2cd2b1cb9dd57ce90c06a1ca84720a2dc75e6332cffebba6086cb75d3","src/methods.rs":"24bdbcb0e3570c8bf3fa270dd8d79dd6dfcb982276c82180a89a1e73c5e38019","src/nom.rs":"b0a9c7ce0d09388179bce8f8e23bf57df76b504d925815583c249ec3fc04baab","src/regexp.rs":"8fdae52b761dbad90179e6be87e0e66357fefa34d76af541fb0fcf550fd6ec08","src/str.rs":"198fa15d45c3636289d92c0a592002a07e5a04a431e8cfdf724266e44d484be2","src/stream.rs":"c1bd5b8e7a2061ff66eb2c954033146001f1d65a26d12efa06af8cf93ffa53e4","src/util.rs":"da40ebac865d3176567d3a37b01170234398a03e938553720ce30aa1f6005b6d","tests/arithmetic.rs":"b98936b7fa0228835ca022f6db5342b72a9c01cc3f16a4e05263bbe6424ba3e9","tests/arithmetic_ast.rs":"b18b9a46ba573ae13c40a31217425f6e8cf8fade09a75cdbbfa7146ec668f0b2","tests/cross_function_backtracking.rs":"b071d13031c1f12195473186e3775943991496b10f4590db3f36d511e9f98a1c","tests/ini.rs":"776f681542028564899e55f71533b3bcda5ed1bbb971f24b5b1b9578111ba0cb","tests/ini_str.rs":"315046d9b6dc38d6d306d3562d7ac6518c9ecce9aabcc58fb80c07577ad99789","tests/issues.rs":"2193c219397b7a417cc009b72c13adc42471e7a4917a2a4009aa0fca23c6ea8c","tests/mp4.rs":"b4bf0514fd645160851cc4da9ad6bf81d571cd14865bf134837c19578caaf6e6","tests/omnom.rs":"409d2349fa24f3503bd02e0079c1554a58ce3d40dd7eb0e5d4bb63b588afdae4","tests/test1.rs":"3e0c187bad91d822ebc113eb5cf30fc6585e53a961728304ac24e05ab2123d10"},"package":"a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"}
|
|
@ -1,46 +0,0 @@
|
|||
language: rust
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libcurl4-openssl-dev
|
||||
- libelf-dev
|
||||
- libdw-dev
|
||||
|
||||
rust:
|
||||
- nightly
|
||||
- beta
|
||||
- stable
|
||||
- 1.2.0
|
||||
|
||||
before_script:
|
||||
- pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
|
||||
|
||||
script:
|
||||
- |
|
||||
travis-cargo --only 1.2 test -- --features regexp &&
|
||||
travis-cargo --only stable test -- --features "regexp regexp_macros" &&
|
||||
travis-cargo --only beta test -- --features "regexp regexp_macros" &&
|
||||
travis-cargo --only nightly build -- --features "nightly core regexp" &&
|
||||
travis-cargo --only nightly test -- --features "regexp" &&
|
||||
travis-cargo bench &&
|
||||
travis-cargo --only stable doc -- --features "regexp"
|
||||
|
||||
after_success:
|
||||
- travis-cargo coveralls --no-sudo
|
||||
|
||||
notifications:
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/9c035a194ac4fd4cc061
|
||||
on_success: change
|
||||
on_failure: always
|
||||
on_start: false
|
||||
|
||||
|
||||
env:
|
||||
global:
|
||||
# override the default `--features unstable` used for the nightly branch (optional)
|
||||
- TRAVIS_CARGO_NIGHTLY_FEATURE=nightly
|
||||
|
||||
sudo: false
|
|
@ -1,555 +0,0 @@
|
|||
# Change Log
|
||||
|
||||
## [Unreleased][unreleased]
|
||||
|
||||
### Changed
|
||||
|
||||
## 1.2.4 - 2016-07-20
|
||||
|
||||
### Thanks
|
||||
- @Phlosioneer for documentation fixes
|
||||
- @sourrust for fixing offsets in `take_bits!`
|
||||
- @ChrisMacNaughton for the XFS crate
|
||||
- @pwoolcoc for `rest_s`
|
||||
- @fitzgen for more `IResult` methods
|
||||
- @gtors for the negative lookahead feature
|
||||
- @frk1 and @jeandudey for little endian float parsing
|
||||
- @jethrogb for fixing input usage in `many1`
|
||||
- @acatton for beating me at nom golf :D
|
||||
|
||||
### Added
|
||||
- the `rest_s` method on `IResult` returns the remaining `&str` input
|
||||
- `unwrap_err` and `unwrap_inc` methods on `IResult`
|
||||
- `not!` will peek at the input and return `Done` if the underlying parser returned `Error` or `Incomplete`, without consuming the input
|
||||
- `le_f32` and `le_f64` parse little endian floating point numbers (IEEE 754)
|
||||
-
|
||||
|
||||
### Fixed
|
||||
- documentation fixes
|
||||
- `take_bits!` is now more precise
|
||||
- `many1` inccorectly used the `len` function instead of `input_len`
|
||||
- the INI parser is simpler
|
||||
- `recognize!` had an early `return` taht is removed now
|
||||
|
||||
## 1.2.3 - 2016-05-10
|
||||
|
||||
### Thanks
|
||||
- @lu-zero for the contribution guidelines
|
||||
- @GuillaumeGomez for fixes on `length_bytes` and some documentation
|
||||
- @Hywan for ducomentation and test fixes
|
||||
- @Xirdus for correct trait import issues
|
||||
- @mspiegel for the new AST example
|
||||
- @cholcombe973 for adding the `cond_with_error!` combinator
|
||||
- @tstorch for refactoring `many0!`
|
||||
- @panicbit for the folding combinators
|
||||
- @evestera for `separated_list!` fixes
|
||||
- @DanielKeep for correcting some enum imports
|
||||
|
||||
### Added
|
||||
- Regular expression combinators starting with `re_bytes_` work on byte slices
|
||||
- example parsing arithmetic expressions to an AST
|
||||
- `cond_with_error!` works like `cond!` but will return `None` if the condition is false, and `Some(value)` if the underlying parser succeeded
|
||||
- `fold_many0!`, `fold_many1!` and `fold_many_m_n!` will take a parser, an initial value and a combining function, and fold over the successful applications of the parser
|
||||
|
||||
### Fixed
|
||||
- `length_bytes!` converts the result of its child parser to usize
|
||||
- `take_till!` now imports `InputLength` instead of assuming it's in scope
|
||||
- `separated_list!` and `separated_nonempty_list!` will not consume the separator if there's no following successfully parsed value
|
||||
- no more warnings on build
|
||||
|
||||
### Changed
|
||||
- simpler implementation of `many0!`
|
||||
|
||||
## 1.2.2 - 2016-03-09
|
||||
|
||||
### Thanks
|
||||
- @conradev for fixing take_until_s!`
|
||||
- @GuillaumeGomez for some documentation fixes
|
||||
- @frewsxcv for some documentation fixes
|
||||
- @tstorch for some test refactorings
|
||||
|
||||
### Added
|
||||
- `nom::Err` now implements `std::error::Error`
|
||||
|
||||
### Fixed
|
||||
- `hex_u32` does not parses more than 8 chars now
|
||||
- `take_while!` and `take_while1!` will not perturb the behaviour of `recognize!` anymore
|
||||
|
||||
## 1.2.1 - 2016-02-23
|
||||
|
||||
### Thanks
|
||||
- @sourrust for adding methods to `IResult`
|
||||
- @tstorch for the test refactoring, and for adding methods to `IResult` and `Needed`
|
||||
- @joelself for fixing the method system
|
||||
|
||||
### Added
|
||||
|
||||
- mapping methods over `IResult` and `Needed`
|
||||
|
||||
### Changed
|
||||
|
||||
- `apply_rf` is renamed to `apply_m`. This will not warrant a major version, since it is part missing from the methods feture added in the 1.2.0 release
|
||||
- the `regexp_macros` feature that used `regex!` to precompile regular expressions has been replaced by the normal regex engine combined with `lazy_static`
|
||||
|
||||
### Fixed
|
||||
|
||||
- when a parser or combinator was returning an empty buffer as remaining part, it was generating one from a static empty string. This was messing with buffer offset calculation. Now, that empty slice is taken like this: `&input[input.len()..]`.
|
||||
- The `regexp_macros` and `no_std` feature build again and are now tested with Travis CI
|
||||
|
||||
## 1.2.0 - 2016-02-08
|
||||
|
||||
### Thanks
|
||||
- @zentner-kyle for type inference fixes
|
||||
- @joelself for his work on `&str` parsing and method parsers
|
||||
- @GuillaumeGomez for implementing methods on `IResult`
|
||||
- @dirk for the `alt_complete!` combinator
|
||||
- @tstorch for a lot of refactoring work and unit tests additions
|
||||
- @jansegre for the hex digit parsers
|
||||
- @belgum for some documentation fixes
|
||||
- @lwandrebeck for some documentation fixes and code fixes in `hex_digit`
|
||||
|
||||
### Added
|
||||
- `take_until_and_consume_s!` for consumption of string data until a tag
|
||||
- more function patterns in `named!`. The error type can now be specified
|
||||
- `alt_complete!` works like the `alt!` combinator, but tries the next branch if the current one returned `Incomplete`, instead of returning directly
|
||||
- more unit tests for a lot of combinators
|
||||
- hexadecimal digit parsers
|
||||
- the `tuple!` combinator takes a list of parsers as argument, and applies them serially on the input. If all of them are successful, it willr eturn a tuple accumulating all the values. This combinator will (hopefully) replace most uses of `chain!`
|
||||
- parsers can now be implemented as a method for a struct thanks to the `method!`, `call_m!` and `apply_rf!` combinators
|
||||
|
||||
### Fixed
|
||||
- there were type inference issues in a few combinators. They will now be easier to compile
|
||||
- `peek!` compilation with bare functions
|
||||
- `&str` parsers were splitting data at the byte level, not at the char level, which can result in inconsistencies in parsing UTF-8 characters. They now use character indexes
|
||||
- some method implementations were missing on `ÌResult<I,O,E>` (with specified error type instead of implicit)
|
||||
|
||||
## 1.1.0 - 2016-01-01
|
||||
|
||||
This release adds a lot of features related to `&str` parsing. The previous versions
|
||||
were focused on `&[u8]` and bit streams parsing, but there's a need for more text
|
||||
parsing with nom. The parsing functions like `alpha`, `digit` and others will now
|
||||
accept either a `&[u8]` or a `&str`, so there is no breaking change on that part.
|
||||
|
||||
There are also a few performance improvements and documentation fixes.
|
||||
|
||||
### Thanks
|
||||
- @Binero for pushing the work on `&str` parsing
|
||||
- @meh for fixing `Option` and `Vec` imports
|
||||
- @hoodie for a documentation fix
|
||||
- @joelself for some documentation fixes
|
||||
- @vberger for his traits magic making `nom functions more generic
|
||||
|
||||
### Added
|
||||
|
||||
- string related parsers: `tag_s!`, `take_s!`, `is_a_s!`, `is_not_s!`, `take_while_s!`, `take_while1_s!`, `take_till_s!
|
||||
- `value!` is a combinator that always returns the same value. If a child parser is passed as second argument, that value is returned when the child parser succeeds
|
||||
|
||||
### Changed
|
||||
|
||||
- `tag!` will now compare even on partial input. If it expects "abcd" but receives "ef", it will now return an `Error` instead of `Incomplete`
|
||||
- `many0!` and others will preallocate a larger vector to avoid some copies and reallocations
|
||||
- `alpha`, `digit`, `alphanumeric`, `space` and `multispace` now accept as input a `&[u8]` or a `&str`. Additionally, they return an error if they receive an empty input
|
||||
- `take_while!`, `take_while1!`, `take_while_s!`, `take_while1_s!` wilreturn an error on empty input
|
||||
|
||||
### Fixed
|
||||
|
||||
- if the child parser of `many0!` or `many1!` returns `Incomplete`, it will return `Incomplete` too, possibly updating the needed size
|
||||
- `Option,` `Some`, `None` and `Vec` are now used with full path imports
|
||||
|
||||
## 1.0.1 - 2015-11-22
|
||||
|
||||
This releases makes the 1.0 version compatible with Rust 1.2 and 1.3
|
||||
|
||||
### Thanks
|
||||
- @steveklabnik for fixing lifetime issues in Producers and Consumers
|
||||
|
||||
## 1.0.0 - 2015-11-16
|
||||
|
||||
Stable release for nom. A lot of new features, a few breaking changes
|
||||
|
||||
### Thanks
|
||||
- @ahenry for macro fixes
|
||||
- @bluss for fixing documentation
|
||||
- @sourrust for cleaning code and debugging the new streaming utilities
|
||||
- @meh for inline optimizations
|
||||
- @ccmtaylor for fixing function imports
|
||||
- @soro for improvements to the streaming utilities
|
||||
- @breard-r for catching my typos
|
||||
- @nelsonjchen for catching my typos too
|
||||
- @divarvel for hex string parsers
|
||||
- @mrordinaire for the `length_bytes!` combinator
|
||||
|
||||
### Breaking changes
|
||||
- `IResult::Error` can now use custom error types, and is generic over the input type
|
||||
- Producers and consumers have been replaced. The new implementation uses less memory and integrates more with parsers
|
||||
- `nom::ErrorCode` is now `nom::ErrorKind`
|
||||
- `filter!` has been renamed to `take_while!`
|
||||
- `chain!` will count how much data is consumed and use that number to calculate how much data is needed if a parser returned `Incomplete`
|
||||
- `alt!` returns `Incomplete` if a child parser returned `Incomplete`, instead of skipping to the next parser
|
||||
- `IResult` does not require a lifetime tag anymore, yay!
|
||||
|
||||
### Added
|
||||
|
||||
- `complete!` will return an error if the child parser returned `Incomplete`
|
||||
- `add_error!` will wrap an error, but allow backtracking
|
||||
- `hex_u32` parser
|
||||
|
||||
### Fixed
|
||||
- the behaviour around `Incomplete` is better for most parsers now
|
||||
|
||||
## 0.5.0 - 2015-10-16
|
||||
|
||||
This release fixes a few issues and stabilizes the code.
|
||||
|
||||
### Thanks
|
||||
- @nox for documentation fixes
|
||||
- @daboross for linting fixes
|
||||
- @ahenry for fixing `tap!` and extending `dbg!` and `dbg_dmp!`
|
||||
- @bluss for tracking down and fixing issues with unsafe code
|
||||
- @meh for inlining parser functions
|
||||
- @ccmtaylor for fixing import of `str::from_utf8`
|
||||
|
||||
### Fixed
|
||||
- `tap!`, `dbg!` and `dbg_dmp!` now accept function parameters
|
||||
|
||||
### Changed
|
||||
- the type used in `count_fixed!` must be `Copy`
|
||||
- `chain!` calculates how much data is needed if one of the parsers returns `Incomplete
|
||||
- optional parsers in `chain!` can return `Incomplete`
|
||||
|
||||
## 0.4.0 - 2015-09-08
|
||||
|
||||
Considering the number of changes since the last release, this version can contain breaking changes, so the version number becomes 0.4.0. A lot of new features and performance improvements!
|
||||
|
||||
### Thanks
|
||||
- @frewsxcv for documentation fixes
|
||||
- @ngrewe for his work on producers and consumers
|
||||
- @meh for fixes on `chain!` and for the `rest` parser
|
||||
- @daboross for refactoring `many0!` and `many1!`
|
||||
- @aleksander for the `switch!` combinator idea
|
||||
- @TechnoMancer for his help with bit level parsing
|
||||
- @sxeraverx for pointing out a bug in `is_a!`
|
||||
|
||||
### Fixed
|
||||
- `count_fixed!` must take an explicit type as argument to generate the fixed-size array
|
||||
- optional parsing behaviour in `chain!`
|
||||
- `count!` can take 0 elements
|
||||
- `is_a!` and `is_not!` can now consume the whole input
|
||||
|
||||
### Added
|
||||
- it is now possible to seek to the end of a `MemProducer`
|
||||
- `opt!` returns `Done(input, None)` if `the child parser returned `Incomplete`
|
||||
- `rest` will return the remaining input
|
||||
- consumers can now seek to and from the end of input
|
||||
- `switch!` applies a first parser then matches on its result to choose the next parser
|
||||
- bit-level parsers
|
||||
- character-level parsers
|
||||
- regular expression parsers
|
||||
- implementation of `take_till!`, `take_while!` and `take_while1!`
|
||||
|
||||
### Changed
|
||||
- `alt!` can return `Incomplete`
|
||||
- the error analysis functions will now take references to functions instead of moving them
|
||||
- performance improvements on producers
|
||||
- performance improvement for `filter!`
|
||||
- performance improvement for `count!`: a `Vec` of the right size is directly allocated
|
||||
|
||||
## 0.3.11 - 2015-08-04
|
||||
|
||||
### Thanks
|
||||
- @bluss for remarking that the crate included random junk lying non commited in my local repository
|
||||
|
||||
### Fixed
|
||||
- cleanup of my local repository will ship less files in the crates, resulting in a smaller download
|
||||
|
||||
## 0.3.10 - 2015-08-03
|
||||
|
||||
### Added
|
||||
|
||||
- `bits!` for bit level parsing. It indicates that all child parsers will take a `(&[u8], usize)`as input, with the second parameter indicating the bit offset in the first byte. This allows viewing a byte slice as a bit stream. Most combinators can be used directly under `bits!`
|
||||
- `take_bits!` takes an integer type and a number of bits, consumes that number of bits and updates the offset, possibly by crossing byte boundaries
|
||||
- bit level parsers are all written in `src/bits.rs`
|
||||
|
||||
### Changed
|
||||
|
||||
- Parsers that specifically handle bytes have been moved to src/bytes.rs`. This applies to `tag!`, `is_not!`, `is_a!`, `filter!`, `take!`, `take_str!`, `take_until_and_consume!`, `take_until!`, `take_until_either_and_consume!`, `take_until_either!`
|
||||
|
||||
## 0.3.9 - 2015-07-20
|
||||
|
||||
### Thanks
|
||||
- @badboy for fixing `filter!`
|
||||
- @idmit for some documentation fixes
|
||||
|
||||
### Added
|
||||
- `opt_res!` applies a parser and transform its result in a Result. This parser never fails
|
||||
- `cond_reduce!` takes an expression as parameter, applies the parser if the expression is true, and returns an error if the expression is false
|
||||
- `tap!` pass the result of a parser to a block to manipulate it, but do not affect the parser's result
|
||||
- `AccReader` is a Read+BufRead that supports data accumulation and partial consumption. The `consume` method must be called afterwardsto indicate how much was consumed
|
||||
- Arithmetic expression evaluation and parsing example
|
||||
- `u16!`, `u32!`, `u64!`, `i16!`, `i32!`, `i64!` take an expression as parameter, if the expression is true, apply the big endian integer parser, if false, the little endian version
|
||||
- type information for combinators. This will make the documentation a bit easier to navigate
|
||||
|
||||
### Fixed
|
||||
- `map_opt!` and `map_res!` had issues with argument order due to bad macros
|
||||
- `delimited!` did not compile for certain combinations of arguments
|
||||
- `filter!` did not return a byte slice but a fixed array
|
||||
|
||||
## 0.3.8 - 2015-07-03
|
||||
|
||||
### Added
|
||||
- code coverage is now calculated automatically on Travis CI
|
||||
- `Stepper`: wrap a `Producer`, and call the method `step` with a parser. This method will buffer data if there is not enough, apply the parser if there is, and keep the rest of the input in memory for the next call
|
||||
- `ReadProducer`: takes something implementing `Read`, and makes a `Producer` out of it
|
||||
|
||||
### Fixed
|
||||
- the combinators `separated_pair!` and `delimited!` did not work because an implementation macro was not exported
|
||||
- if a `MemProducer` reached its end, it should always return `Eof`
|
||||
- `map!` had issues with argument matching
|
||||
|
||||
## 0.3.7 - 2015-06-24
|
||||
|
||||
### Added
|
||||
- `expr_res!` and `expr_opt!` evaluate an expression returning a Result or Opt and convert it to IResult
|
||||
- `AsBytes` is implemented for fixed size arrays. This allows `tag!([41u8, 42u8])`
|
||||
|
||||
### Fixed
|
||||
- `count_fixed!` argument parsing works again
|
||||
|
||||
## 0.3.6 - 2015-06-15
|
||||
|
||||
### Added
|
||||
- documentation for a few functions
|
||||
- the consumer trait now requires the `failed(&self, error_code)` method in case of parsing error
|
||||
- `named!` now handles thge alternative `named!(pub fun_name<OutputType>, ...)`
|
||||
|
||||
### Fixed
|
||||
- `filter!` now returns the whole input if the filter function never returned false
|
||||
- `take!` casts its argument as usize, so it can accepts any integer type now
|
||||
|
||||
## 0.3.5 - 2015-06-10
|
||||
|
||||
### Thanks
|
||||
- @cmr for some documentation fixes
|
||||
|
||||
### Added
|
||||
- `count_fixed!` returns a fixed array
|
||||
|
||||
### Fixed
|
||||
- `count!` is back to the previous behaviour, returning a `Vec` for sizes known at runtime
|
||||
|
||||
### Changed
|
||||
- functions and traits exported from `nom::util` are now directly in `nom::`
|
||||
|
||||
## 0.3.4 - 2015-06-09
|
||||
|
||||
### Thanks
|
||||
- @andrew-d for fixes on `cond!`
|
||||
- @keruspe for features in `chain!`
|
||||
|
||||
### Added
|
||||
- `chain!` can now have mutable fields
|
||||
|
||||
### Fixed
|
||||
- `cond!` had an infinite macro recursion
|
||||
|
||||
### Changed
|
||||
- `chain!` generates less code now. No apprent compilation time improvement
|
||||
|
||||
## 0.3.3 - 2015-06-09
|
||||
|
||||
### Thanks
|
||||
- @andrew-d for the little endian signed integer parsers
|
||||
- @keruspe for fixes on `count!`
|
||||
|
||||
### Added
|
||||
- `le_i8`, `le_i16`, `le_i32`, `le_i64`: little endian signed integer parsers
|
||||
|
||||
### Changed
|
||||
- the `alt!` parser compiles much faster, even with more than 8 branches
|
||||
- `count!` can now return a fixed size array instead of a growable vector
|
||||
|
||||
## 0.3.2 - 2015-05-31
|
||||
|
||||
### Thanks
|
||||
- @keruspe for the `take_str` parser and the function application combinator
|
||||
|
||||
### Added
|
||||
- `take_str!`: takes the specified number of bytes and return a UTF-8 string
|
||||
- `apply!`: do partial application on the parameters of a function
|
||||
|
||||
### Changed
|
||||
- `Needed::Size` now contains a `usize` instead of a `u32`
|
||||
|
||||
## 0.3.1 - 2015-05-21
|
||||
|
||||
### Thanks
|
||||
- @divarvel for the big endian signed integer parsers
|
||||
|
||||
### Added
|
||||
- `be_i8`, `be_i16`, `be_i32`, `be_i64`: big endian signed integer parsers
|
||||
- the `core` feature can be passed to cargo to build with `no_std`
|
||||
- colored hexdump can be generated from error chains
|
||||
|
||||
## 0.3.0 - 2015-05-07
|
||||
|
||||
### Thanks
|
||||
- @filipegoncalves for some documentation and the new eof parser
|
||||
- @CrimsonVoid for putting fully qualified types in the macros
|
||||
- @lu_zero for some documentation fixes
|
||||
|
||||
### Added
|
||||
- new error types that can contain an error code, an input slice, and a list of following errors
|
||||
- `error!` will cut backtracking and return directly from the parser, with a specified error code
|
||||
- `eof` parser, successful if there is no more input
|
||||
- specific error codes for the parsers provided by nom
|
||||
|
||||
### Changed
|
||||
- fully qualified types in macros. A lot of imports are not needed anymore
|
||||
|
||||
### Removed
|
||||
- `FlatMap`, `FlatpMapOpt` and `Functor` traits (replaced by `map!`, `map_opt!` and `map_res!`)
|
||||
|
||||
## 0.2.2 - 2015-04-12
|
||||
|
||||
### Thanks
|
||||
- @filipegoncalves and @thehydroimpulse for debugging an infinite loop in many0 and many1
|
||||
- @thehydroimpulse for suggesting public named parsers
|
||||
- @skade for removing the dependency on the collections gate
|
||||
|
||||
### Added
|
||||
- `named!` can now declare public functions like this: `named!(pub tst, tag!("abcd"));`
|
||||
- `pair!(X,Y)` returns a tuple `(x, y)`
|
||||
- `separated_pair!(X, sep, Y)` returns a tuple `(x, y)`
|
||||
- `preceded!(opening, X)` returns `x`
|
||||
- `terminated!(X, closing)` returns `x`
|
||||
- `delimited(opening, X, closing)` returns `x`
|
||||
- `separated_list(sep, X)` returns a `Vec<X>`
|
||||
- `separated_nonempty_list(sep, X)` returns a `Vec<X>` of at list one element
|
||||
|
||||
### Changed
|
||||
- `many0!` and `many1!` forbid parsers that do not consume input
|
||||
- `is_a!`, `is_not!`, `alpha`, `digit`, `space`, `multispace` will now return an error if they do not consume at least one byte
|
||||
|
||||
## 0.2.1 - 2015-04-04
|
||||
|
||||
### Thanks
|
||||
- @mtsr for catching the remaining debug println!
|
||||
- @jag426 who killed a lot of warnings
|
||||
- @skade for removing the dependency on the core feature gate
|
||||
|
||||
|
||||
### Added
|
||||
- little endian unsigned int parsers le_u8, le_u16, le_u32, le_u64
|
||||
- `count!` to apply a parser a specified number of times
|
||||
- `cond!` applies a parser if the condition is met
|
||||
- more parser development tools in `util::*`
|
||||
|
||||
### Fixed
|
||||
- in one case, `opt!` would not compile
|
||||
|
||||
### Removed
|
||||
- most of the feature gates are now removed. The only one still needed is `collections`
|
||||
|
||||
## 0.2.0 - 2015-03-24
|
||||
*works with `rustc 1.0.0-dev (81e2396c7 2015-03-19) (built 2015-03-19)`*
|
||||
|
||||
### Thanks
|
||||
- Ryman for the AsBytes implementation
|
||||
- jag426 and jaredly for documentation fixes
|
||||
- eternaleye on #rust IRC for his help on the new macro syntax
|
||||
|
||||
### Changed
|
||||
- the AsBytes trait improves readability, no more b"...", but "..." instead
|
||||
- Incomplete will now hold either Needed;;Unknown, or Needed::Size(u32). Matching on Incomplete without caring for the value is done with `Incomplete(_)`, but if more granularity is mandatory, `Needed` can be matched too
|
||||
- `alt!` can pass the result of the parser to a closure
|
||||
- the `take_*` macros changed behaviour, the default case is now not to consume the separator. The macros have been renamed as follows: `take_until!` -> `take_until_and_consume!`, `take_until_and_leave!` -> `take_until!`, `take_until_either_and_leave!` -> `take_until_either!`, `take_until_either!` -> `take_until_either_and_consume!`
|
||||
|
||||
### Added
|
||||
- `peek!` macro: matches the future input but does not consume it
|
||||
- `length_value!` macro: the first argument is a parser returning a `n` that can cast to usize, then applies the second parser `n` times. The macro has a variant with a third argument indicating the expected input size for the second parser
|
||||
- benchmarks are available at https://github.com/Geal/nom_benchmarks
|
||||
- more documentation
|
||||
- **Unnamed parser syntax**: warning, this is a breaking change. With this new syntax, the macro combinators do not generate functions anymore, they create blocks. That way, they can be nested, for better readability. The `named!` macro is provided to create functions from parsers. Please be aware that nesting parsers comes with a small cost of compilation time, negligible in most cases, but can quickly get to the minutes scale if not careful. If this happens, separate your parsers in multiple subfunctions.
|
||||
- `named!`, `closure!` and `call!` macros used to support the unnamed syntax
|
||||
- `map!`, `map_opt!` and `map_res!` to combine a parser with a normal function, transforming the input directly, or returning an `Option` or `Result`
|
||||
|
||||
### Fixed
|
||||
- `is_a!` is now working properly
|
||||
|
||||
### Removed
|
||||
- the `o!` macro does less than `chain!`, so it has been removed
|
||||
- the `fold0!` and `fold1!` macros were too complex and awkward to use, the `many*` combinators will be useful for most uses for now
|
||||
|
||||
## 0.1.6 - 2015-02-24
|
||||
### Changed
|
||||
- consumers must have an end method that will be called after parsing
|
||||
|
||||
### Added
|
||||
- big endian unsigned int and float parsers: be_u8, be_u16, be_u32, be_u64, be_f32, be_f64
|
||||
- producers can seek
|
||||
- function and macros documentation
|
||||
- README documentation
|
||||
### Fixed
|
||||
- lifetime declarations
|
||||
- tag! can return Incomplete
|
||||
|
||||
## 0.1.5 - 2015-02-17
|
||||
### Changed
|
||||
- traits were renamed: FlatMapper -> FlatMap, Mapper -> FlatMapOpt, Mapper2 -> Functor
|
||||
|
||||
### Fixed
|
||||
- woeks with rustc f1bb6c2f4
|
||||
|
||||
## 0.1.4 - 2015-02-17
|
||||
### Changed
|
||||
- the chaining macro can take optional arguments with '?'
|
||||
|
||||
## 0.1.3 - 2015-02-16
|
||||
### Changed
|
||||
- the chaining macro now takes the closure at the end of the argument list
|
||||
|
||||
## 0.1.2 - 2015-02-16
|
||||
### Added
|
||||
- flat_map implementation for <&[u8], &[u8]>
|
||||
- chaining macro
|
||||
- partial MP4 parser example
|
||||
|
||||
|
||||
## 0.1.1 - 2015-02-06
|
||||
### Fixed
|
||||
- closure syntax change
|
||||
|
||||
## Compare code
|
||||
|
||||
* [unreleased]: https://github.com/Geal/nom/compare/1.2.4...HEAD
|
||||
* [1.2.3]: https://github.com/Geal/nom/compare/1.2.3...1.2.4
|
||||
* [1.2.3]: https://github.com/Geal/nom/compare/1.2.2...1.2.3
|
||||
* [1.2.2]: https://github.com/Geal/nom/compare/1.2.1...1.2.2
|
||||
* [1.2.1]: https://github.com/Geal/nom/compare/1.2.0...1.2.1
|
||||
* [1.2.0]: https://github.com/Geal/nom/compare/1.1.0...1.2.0
|
||||
* [1.1.0]: https://github.com/Geal/nom/compare/1.0.1...1.1.0
|
||||
* [1.0.1]: https://github.com/Geal/nom/compare/1.0.0...1.0.1
|
||||
* [1.0.0]: https://github.com/Geal/nom/compare/0.5.0...1.0.0
|
||||
* [0.5.0]: https://github.com/geal/nom/compare/0.4.0...0.5.0
|
||||
* [0.4.0]: https://github.com/geal/nom/compare/0.3.11...0.4.0
|
||||
* [0.3.11]: https://github.com/geal/nom/compare/0.3.10...0.3.11
|
||||
* [0.3.10]: https://github.com/geal/nom/compare/0.3.9...0.3.10
|
||||
* [0.3.9]: https://github.com/geal/nom/compare/0.3.8...0.3.9
|
||||
* [0.3.8]: https://github.com/Geal/nom/compare/0.3.7...0.3.8
|
||||
* [0.3.7]: https://github.com/Geal/nom/compare/0.3.6...0.3.7
|
||||
* [0.3.6]: https://github.com/Geal/nom/compare/0.3.5...0.3.6
|
||||
* [0.3.5]: https://github.com/Geal/nom/compare/0.3.4...0.3.5
|
||||
* [0.3.4]: https://github.com/Geal/nom/compare/0.3.3...0.3.4
|
||||
* [0.3.3]: https://github.com/Geal/nom/compare/0.3.2...0.3.3
|
||||
* [0.3.2]: https://github.com/Geal/nom/compare/0.3.1...0.3.2
|
||||
* [0.3.1]: https://github.com/Geal/nom/compare/0.3.0...0.3.1
|
||||
* [0.3.0]: https://github.com/Geal/nom/compare/0.2.2...0.3.0
|
||||
* [0.2.2]: https://github.com/Geal/nom/compare/0.2.1...0.2.2
|
||||
* [0.2.1]: https://github.com/Geal/nom/compare/0.2.0...0.2.1
|
||||
* [0.2.0]: https://github.com/Geal/nom/compare/0.1.6...0.2.0
|
||||
* [0.1.6]: https://github.com/Geal/nom/compare/0.1.5...0.1.6
|
||||
* [0.1.5]: https://github.com/Geal/nom/compare/0.1.4...0.1.5
|
||||
* [0.1.4]: https://github.com/Geal/nom/compare/0.1.3...0.1.4
|
||||
* [0.1.3]: https://github.com/Geal/nom/compare/0.1.2...0.1.3
|
||||
* [0.1.2]: https://github.com/Geal/nom/compare/0.1.1...0.1.2
|
||||
* [0.1.1]: https://github.com/Geal/nom/compare/0.1.0...0.1.1
|
|
@ -1,38 +0,0 @@
|
|||
[package]
|
||||
|
||||
name = "nom"
|
||||
version = "1.2.4"
|
||||
authors = [ "contact@geoffroycouprie.com" ]
|
||||
description = "A byte-oriented, zero-copy, parser combinators library"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/Geal/nom"
|
||||
readme = "README.md"
|
||||
documentation = "http://rust.unhandledexpression.com/nom/"
|
||||
keywords = ["parser", "parser-combinators", "parsing", "streaming", "bit"]
|
||||
|
||||
include = [
|
||||
"CHANGELOG.md",
|
||||
"LICENSE",
|
||||
".gitignore",
|
||||
".travis.yml",
|
||||
"Cargo.toml",
|
||||
"src/*.rs",
|
||||
"tests/*.rs"
|
||||
]
|
||||
|
||||
[features]
|
||||
core = []
|
||||
nightly = []
|
||||
default = ["stream"]
|
||||
regexp = ["regex"]
|
||||
regexp_macros = ["regexp", "lazy_static"]
|
||||
stream = []
|
||||
|
||||
[dependencies.regex]
|
||||
version = "^0.1.56"
|
||||
optional = true
|
||||
|
||||
[dependencies.lazy_static]
|
||||
version = "^0.2.1"
|
||||
optional = true
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
Copyright (c) 2015 Geoffroy Couprie
|
||||
|
||||
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.
|
|
@ -1 +0,0 @@
|
|||
{"files":{".travis.yml":"6d4e81838b10c5e330749857c72c2f2b1a2e575e71abcd11c094f3b612347b2a","CHANGELOG.md":"d4722e028b2a5b88c466b0d759e463b90bdcfa1b79181a1c76cd313b0a27c615","Cargo.toml":"aebcb999933c3425db85012bea19f9ce78da8e7834dbab54d4a2966e8bc62149","LICENSE":"de730187d5563a81342a3c011d968f78dff37c934fac9b3701e8c762b6118a55","src/bits.rs":"97c9148f63e175489bb6199d039c594ddc56bdf0b7491b9f38b8d74e898bca80","src/bytes.rs":"8f29b976a5e8e6500eb618a9dead7f212688ba9eb06c7066a4016e2db99fed00","src/character.rs":"9ee081f56b508212231ff70d7455b1b85ae44722a39aa60223e8cd95c6570859","src/internal.rs":"ada499b9c178be2a7f9b56319ffb10a778f25fafcda39c78d26b364d89debd72","src/lib.rs":"34efb051214acfde2053e93a7ba718a4fd41b6e0d9edd65a1737605d99b994ab","src/macros.rs":"d39ce3a2cd2b1cb9dd57ce90c06a1ca84720a2dc75e6332cffebba6086cb75d3","src/methods.rs":"24bdbcb0e3570c8bf3fa270dd8d79dd6dfcb982276c82180a89a1e73c5e38019","src/nom.rs":"b0a9c7ce0d09388179bce8f8e23bf57df76b504d925815583c249ec3fc04baab","src/regexp.rs":"8fdae52b761dbad90179e6be87e0e66357fefa34d76af541fb0fcf550fd6ec08","src/str.rs":"198fa15d45c3636289d92c0a592002a07e5a04a431e8cfdf724266e44d484be2","src/stream.rs":"c1bd5b8e7a2061ff66eb2c954033146001f1d65a26d12efa06af8cf93ffa53e4","src/util.rs":"da40ebac865d3176567d3a37b01170234398a03e938553720ce30aa1f6005b6d","tests/arithmetic.rs":"b98936b7fa0228835ca022f6db5342b72a9c01cc3f16a4e05263bbe6424ba3e9","tests/arithmetic_ast.rs":"b18b9a46ba573ae13c40a31217425f6e8cf8fade09a75cdbbfa7146ec668f0b2","tests/cross_function_backtracking.rs":"b071d13031c1f12195473186e3775943991496b10f4590db3f36d511e9f98a1c","tests/ini.rs":"776f681542028564899e55f71533b3bcda5ed1bbb971f24b5b1b9578111ba0cb","tests/ini_str.rs":"315046d9b6dc38d6d306d3562d7ac6518c9ecce9aabcc58fb80c07577ad99789","tests/issues.rs":"2193c219397b7a417cc009b72c13adc42471e7a4917a2a4009aa0fca23c6ea8c","tests/mp4.rs":"b4bf0514fd645160851cc4da9ad6bf81d571cd14865bf134837c19578caaf6e6","tests/omnom.rs":"409d2349fa24f3503bd02e0079c1554a58ce3d40dd7eb0e5d4bb63b588afdae4","tests/test1.rs":"3e0c187bad91d822ebc113eb5cf30fc6585e53a961728304ac24e05ab2123d10"},"package":"a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"}
|
|
@ -1,46 +0,0 @@
|
|||
language: rust
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libcurl4-openssl-dev
|
||||
- libelf-dev
|
||||
- libdw-dev
|
||||
|
||||
rust:
|
||||
- nightly
|
||||
- beta
|
||||
- stable
|
||||
- 1.2.0
|
||||
|
||||
before_script:
|
||||
- pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
|
||||
|
||||
script:
|
||||
- |
|
||||
travis-cargo --only 1.2 test -- --features regexp &&
|
||||
travis-cargo --only stable test -- --features "regexp regexp_macros" &&
|
||||
travis-cargo --only beta test -- --features "regexp regexp_macros" &&
|
||||
travis-cargo --only nightly build -- --features "nightly core regexp" &&
|
||||
travis-cargo --only nightly test -- --features "regexp" &&
|
||||
travis-cargo bench &&
|
||||
travis-cargo --only stable doc -- --features "regexp"
|
||||
|
||||
after_success:
|
||||
- travis-cargo coveralls --no-sudo
|
||||
|
||||
notifications:
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/9c035a194ac4fd4cc061
|
||||
on_success: change
|
||||
on_failure: always
|
||||
on_start: false
|
||||
|
||||
|
||||
env:
|
||||
global:
|
||||
# override the default `--features unstable` used for the nightly branch (optional)
|
||||
- TRAVIS_CARGO_NIGHTLY_FEATURE=nightly
|
||||
|
||||
sudo: false
|
|
@ -1,555 +0,0 @@
|
|||
# Change Log
|
||||
|
||||
## [Unreleased][unreleased]
|
||||
|
||||
### Changed
|
||||
|
||||
## 1.2.4 - 2016-07-20
|
||||
|
||||
### Thanks
|
||||
- @Phlosioneer for documentation fixes
|
||||
- @sourrust for fixing offsets in `take_bits!`
|
||||
- @ChrisMacNaughton for the XFS crate
|
||||
- @pwoolcoc for `rest_s`
|
||||
- @fitzgen for more `IResult` methods
|
||||
- @gtors for the negative lookahead feature
|
||||
- @frk1 and @jeandudey for little endian float parsing
|
||||
- @jethrogb for fixing input usage in `many1`
|
||||
- @acatton for beating me at nom golf :D
|
||||
|
||||
### Added
|
||||
- the `rest_s` method on `IResult` returns the remaining `&str` input
|
||||
- `unwrap_err` and `unwrap_inc` methods on `IResult`
|
||||
- `not!` will peek at the input and return `Done` if the underlying parser returned `Error` or `Incomplete`, without consuming the input
|
||||
- `le_f32` and `le_f64` parse little endian floating point numbers (IEEE 754)
|
||||
-
|
||||
|
||||
### Fixed
|
||||
- documentation fixes
|
||||
- `take_bits!` is now more precise
|
||||
- `many1` inccorectly used the `len` function instead of `input_len`
|
||||
- the INI parser is simpler
|
||||
- `recognize!` had an early `return` taht is removed now
|
||||
|
||||
## 1.2.3 - 2016-05-10
|
||||
|
||||
### Thanks
|
||||
- @lu-zero for the contribution guidelines
|
||||
- @GuillaumeGomez for fixes on `length_bytes` and some documentation
|
||||
- @Hywan for ducomentation and test fixes
|
||||
- @Xirdus for correct trait import issues
|
||||
- @mspiegel for the new AST example
|
||||
- @cholcombe973 for adding the `cond_with_error!` combinator
|
||||
- @tstorch for refactoring `many0!`
|
||||
- @panicbit for the folding combinators
|
||||
- @evestera for `separated_list!` fixes
|
||||
- @DanielKeep for correcting some enum imports
|
||||
|
||||
### Added
|
||||
- Regular expression combinators starting with `re_bytes_` work on byte slices
|
||||
- example parsing arithmetic expressions to an AST
|
||||
- `cond_with_error!` works like `cond!` but will return `None` if the condition is false, and `Some(value)` if the underlying parser succeeded
|
||||
- `fold_many0!`, `fold_many1!` and `fold_many_m_n!` will take a parser, an initial value and a combining function, and fold over the successful applications of the parser
|
||||
|
||||
### Fixed
|
||||
- `length_bytes!` converts the result of its child parser to usize
|
||||
- `take_till!` now imports `InputLength` instead of assuming it's in scope
|
||||
- `separated_list!` and `separated_nonempty_list!` will not consume the separator if there's no following successfully parsed value
|
||||
- no more warnings on build
|
||||
|
||||
### Changed
|
||||
- simpler implementation of `many0!`
|
||||
|
||||
## 1.2.2 - 2016-03-09
|
||||
|
||||
### Thanks
|
||||
- @conradev for fixing take_until_s!`
|
||||
- @GuillaumeGomez for some documentation fixes
|
||||
- @frewsxcv for some documentation fixes
|
||||
- @tstorch for some test refactorings
|
||||
|
||||
### Added
|
||||
- `nom::Err` now implements `std::error::Error`
|
||||
|
||||
### Fixed
|
||||
- `hex_u32` does not parses more than 8 chars now
|
||||
- `take_while!` and `take_while1!` will not perturb the behaviour of `recognize!` anymore
|
||||
|
||||
## 1.2.1 - 2016-02-23
|
||||
|
||||
### Thanks
|
||||
- @sourrust for adding methods to `IResult`
|
||||
- @tstorch for the test refactoring, and for adding methods to `IResult` and `Needed`
|
||||
- @joelself for fixing the method system
|
||||
|
||||
### Added
|
||||
|
||||
- mapping methods over `IResult` and `Needed`
|
||||
|
||||
### Changed
|
||||
|
||||
- `apply_rf` is renamed to `apply_m`. This will not warrant a major version, since it is part missing from the methods feture added in the 1.2.0 release
|
||||
- the `regexp_macros` feature that used `regex!` to precompile regular expressions has been replaced by the normal regex engine combined with `lazy_static`
|
||||
|
||||
### Fixed
|
||||
|
||||
- when a parser or combinator was returning an empty buffer as remaining part, it was generating one from a static empty string. This was messing with buffer offset calculation. Now, that empty slice is taken like this: `&input[input.len()..]`.
|
||||
- The `regexp_macros` and `no_std` feature build again and are now tested with Travis CI
|
||||
|
||||
## 1.2.0 - 2016-02-08
|
||||
|
||||
### Thanks
|
||||
- @zentner-kyle for type inference fixes
|
||||
- @joelself for his work on `&str` parsing and method parsers
|
||||
- @GuillaumeGomez for implementing methods on `IResult`
|
||||
- @dirk for the `alt_complete!` combinator
|
||||
- @tstorch for a lot of refactoring work and unit tests additions
|
||||
- @jansegre for the hex digit parsers
|
||||
- @belgum for some documentation fixes
|
||||
- @lwandrebeck for some documentation fixes and code fixes in `hex_digit`
|
||||
|
||||
### Added
|
||||
- `take_until_and_consume_s!` for consumption of string data until a tag
|
||||
- more function patterns in `named!`. The error type can now be specified
|
||||
- `alt_complete!` works like the `alt!` combinator, but tries the next branch if the current one returned `Incomplete`, instead of returning directly
|
||||
- more unit tests for a lot of combinators
|
||||
- hexadecimal digit parsers
|
||||
- the `tuple!` combinator takes a list of parsers as argument, and applies them serially on the input. If all of them are successful, it willr eturn a tuple accumulating all the values. This combinator will (hopefully) replace most uses of `chain!`
|
||||
- parsers can now be implemented as a method for a struct thanks to the `method!`, `call_m!` and `apply_rf!` combinators
|
||||
|
||||
### Fixed
|
||||
- there were type inference issues in a few combinators. They will now be easier to compile
|
||||
- `peek!` compilation with bare functions
|
||||
- `&str` parsers were splitting data at the byte level, not at the char level, which can result in inconsistencies in parsing UTF-8 characters. They now use character indexes
|
||||
- some method implementations were missing on `ÌResult<I,O,E>` (with specified error type instead of implicit)
|
||||
|
||||
## 1.1.0 - 2016-01-01
|
||||
|
||||
This release adds a lot of features related to `&str` parsing. The previous versions
|
||||
were focused on `&[u8]` and bit streams parsing, but there's a need for more text
|
||||
parsing with nom. The parsing functions like `alpha`, `digit` and others will now
|
||||
accept either a `&[u8]` or a `&str`, so there is no breaking change on that part.
|
||||
|
||||
There are also a few performance improvements and documentation fixes.
|
||||
|
||||
### Thanks
|
||||
- @Binero for pushing the work on `&str` parsing
|
||||
- @meh for fixing `Option` and `Vec` imports
|
||||
- @hoodie for a documentation fix
|
||||
- @joelself for some documentation fixes
|
||||
- @vberger for his traits magic making `nom functions more generic
|
||||
|
||||
### Added
|
||||
|
||||
- string related parsers: `tag_s!`, `take_s!`, `is_a_s!`, `is_not_s!`, `take_while_s!`, `take_while1_s!`, `take_till_s!
|
||||
- `value!` is a combinator that always returns the same value. If a child parser is passed as second argument, that value is returned when the child parser succeeds
|
||||
|
||||
### Changed
|
||||
|
||||
- `tag!` will now compare even on partial input. If it expects "abcd" but receives "ef", it will now return an `Error` instead of `Incomplete`
|
||||
- `many0!` and others will preallocate a larger vector to avoid some copies and reallocations
|
||||
- `alpha`, `digit`, `alphanumeric`, `space` and `multispace` now accept as input a `&[u8]` or a `&str`. Additionally, they return an error if they receive an empty input
|
||||
- `take_while!`, `take_while1!`, `take_while_s!`, `take_while1_s!` wilreturn an error on empty input
|
||||
|
||||
### Fixed
|
||||
|
||||
- if the child parser of `many0!` or `many1!` returns `Incomplete`, it will return `Incomplete` too, possibly updating the needed size
|
||||
- `Option,` `Some`, `None` and `Vec` are now used with full path imports
|
||||
|
||||
## 1.0.1 - 2015-11-22
|
||||
|
||||
This releases makes the 1.0 version compatible with Rust 1.2 and 1.3
|
||||
|
||||
### Thanks
|
||||
- @steveklabnik for fixing lifetime issues in Producers and Consumers
|
||||
|
||||
## 1.0.0 - 2015-11-16
|
||||
|
||||
Stable release for nom. A lot of new features, a few breaking changes
|
||||
|
||||
### Thanks
|
||||
- @ahenry for macro fixes
|
||||
- @bluss for fixing documentation
|
||||
- @sourrust for cleaning code and debugging the new streaming utilities
|
||||
- @meh for inline optimizations
|
||||
- @ccmtaylor for fixing function imports
|
||||
- @soro for improvements to the streaming utilities
|
||||
- @breard-r for catching my typos
|
||||
- @nelsonjchen for catching my typos too
|
||||
- @divarvel for hex string parsers
|
||||
- @mrordinaire for the `length_bytes!` combinator
|
||||
|
||||
### Breaking changes
|
||||
- `IResult::Error` can now use custom error types, and is generic over the input type
|
||||
- Producers and consumers have been replaced. The new implementation uses less memory and integrates more with parsers
|
||||
- `nom::ErrorCode` is now `nom::ErrorKind`
|
||||
- `filter!` has been renamed to `take_while!`
|
||||
- `chain!` will count how much data is consumed and use that number to calculate how much data is needed if a parser returned `Incomplete`
|
||||
- `alt!` returns `Incomplete` if a child parser returned `Incomplete`, instead of skipping to the next parser
|
||||
- `IResult` does not require a lifetime tag anymore, yay!
|
||||
|
||||
### Added
|
||||
|
||||
- `complete!` will return an error if the child parser returned `Incomplete`
|
||||
- `add_error!` will wrap an error, but allow backtracking
|
||||
- `hex_u32` parser
|
||||
|
||||
### Fixed
|
||||
- the behaviour around `Incomplete` is better for most parsers now
|
||||
|
||||
## 0.5.0 - 2015-10-16
|
||||
|
||||
This release fixes a few issues and stabilizes the code.
|
||||
|
||||
### Thanks
|
||||
- @nox for documentation fixes
|
||||
- @daboross for linting fixes
|
||||
- @ahenry for fixing `tap!` and extending `dbg!` and `dbg_dmp!`
|
||||
- @bluss for tracking down and fixing issues with unsafe code
|
||||
- @meh for inlining parser functions
|
||||
- @ccmtaylor for fixing import of `str::from_utf8`
|
||||
|
||||
### Fixed
|
||||
- `tap!`, `dbg!` and `dbg_dmp!` now accept function parameters
|
||||
|
||||
### Changed
|
||||
- the type used in `count_fixed!` must be `Copy`
|
||||
- `chain!` calculates how much data is needed if one of the parsers returns `Incomplete
|
||||
- optional parsers in `chain!` can return `Incomplete`
|
||||
|
||||
## 0.4.0 - 2015-09-08
|
||||
|
||||
Considering the number of changes since the last release, this version can contain breaking changes, so the version number becomes 0.4.0. A lot of new features and performance improvements!
|
||||
|
||||
### Thanks
|
||||
- @frewsxcv for documentation fixes
|
||||
- @ngrewe for his work on producers and consumers
|
||||
- @meh for fixes on `chain!` and for the `rest` parser
|
||||
- @daboross for refactoring `many0!` and `many1!`
|
||||
- @aleksander for the `switch!` combinator idea
|
||||
- @TechnoMancer for his help with bit level parsing
|
||||
- @sxeraverx for pointing out a bug in `is_a!`
|
||||
|
||||
### Fixed
|
||||
- `count_fixed!` must take an explicit type as argument to generate the fixed-size array
|
||||
- optional parsing behaviour in `chain!`
|
||||
- `count!` can take 0 elements
|
||||
- `is_a!` and `is_not!` can now consume the whole input
|
||||
|
||||
### Added
|
||||
- it is now possible to seek to the end of a `MemProducer`
|
||||
- `opt!` returns `Done(input, None)` if `the child parser returned `Incomplete`
|
||||
- `rest` will return the remaining input
|
||||
- consumers can now seek to and from the end of input
|
||||
- `switch!` applies a first parser then matches on its result to choose the next parser
|
||||
- bit-level parsers
|
||||
- character-level parsers
|
||||
- regular expression parsers
|
||||
- implementation of `take_till!`, `take_while!` and `take_while1!`
|
||||
|
||||
### Changed
|
||||
- `alt!` can return `Incomplete`
|
||||
- the error analysis functions will now take references to functions instead of moving them
|
||||
- performance improvements on producers
|
||||
- performance improvement for `filter!`
|
||||
- performance improvement for `count!`: a `Vec` of the right size is directly allocated
|
||||
|
||||
## 0.3.11 - 2015-08-04
|
||||
|
||||
### Thanks
|
||||
- @bluss for remarking that the crate included random junk lying non commited in my local repository
|
||||
|
||||
### Fixed
|
||||
- cleanup of my local repository will ship less files in the crates, resulting in a smaller download
|
||||
|
||||
## 0.3.10 - 2015-08-03
|
||||
|
||||
### Added
|
||||
|
||||
- `bits!` for bit level parsing. It indicates that all child parsers will take a `(&[u8], usize)`as input, with the second parameter indicating the bit offset in the first byte. This allows viewing a byte slice as a bit stream. Most combinators can be used directly under `bits!`
|
||||
- `take_bits!` takes an integer type and a number of bits, consumes that number of bits and updates the offset, possibly by crossing byte boundaries
|
||||
- bit level parsers are all written in `src/bits.rs`
|
||||
|
||||
### Changed
|
||||
|
||||
- Parsers that specifically handle bytes have been moved to src/bytes.rs`. This applies to `tag!`, `is_not!`, `is_a!`, `filter!`, `take!`, `take_str!`, `take_until_and_consume!`, `take_until!`, `take_until_either_and_consume!`, `take_until_either!`
|
||||
|
||||
## 0.3.9 - 2015-07-20
|
||||
|
||||
### Thanks
|
||||
- @badboy for fixing `filter!`
|
||||
- @idmit for some documentation fixes
|
||||
|
||||
### Added
|
||||
- `opt_res!` applies a parser and transform its result in a Result. This parser never fails
|
||||
- `cond_reduce!` takes an expression as parameter, applies the parser if the expression is true, and returns an error if the expression is false
|
||||
- `tap!` pass the result of a parser to a block to manipulate it, but do not affect the parser's result
|
||||
- `AccReader` is a Read+BufRead that supports data accumulation and partial consumption. The `consume` method must be called afterwardsto indicate how much was consumed
|
||||
- Arithmetic expression evaluation and parsing example
|
||||
- `u16!`, `u32!`, `u64!`, `i16!`, `i32!`, `i64!` take an expression as parameter, if the expression is true, apply the big endian integer parser, if false, the little endian version
|
||||
- type information for combinators. This will make the documentation a bit easier to navigate
|
||||
|
||||
### Fixed
|
||||
- `map_opt!` and `map_res!` had issues with argument order due to bad macros
|
||||
- `delimited!` did not compile for certain combinations of arguments
|
||||
- `filter!` did not return a byte slice but a fixed array
|
||||
|
||||
## 0.3.8 - 2015-07-03
|
||||
|
||||
### Added
|
||||
- code coverage is now calculated automatically on Travis CI
|
||||
- `Stepper`: wrap a `Producer`, and call the method `step` with a parser. This method will buffer data if there is not enough, apply the parser if there is, and keep the rest of the input in memory for the next call
|
||||
- `ReadProducer`: takes something implementing `Read`, and makes a `Producer` out of it
|
||||
|
||||
### Fixed
|
||||
- the combinators `separated_pair!` and `delimited!` did not work because an implementation macro was not exported
|
||||
- if a `MemProducer` reached its end, it should always return `Eof`
|
||||
- `map!` had issues with argument matching
|
||||
|
||||
## 0.3.7 - 2015-06-24
|
||||
|
||||
### Added
|
||||
- `expr_res!` and `expr_opt!` evaluate an expression returning a Result or Opt and convert it to IResult
|
||||
- `AsBytes` is implemented for fixed size arrays. This allows `tag!([41u8, 42u8])`
|
||||
|
||||
### Fixed
|
||||
- `count_fixed!` argument parsing works again
|
||||
|
||||
## 0.3.6 - 2015-06-15
|
||||
|
||||
### Added
|
||||
- documentation for a few functions
|
||||
- the consumer trait now requires the `failed(&self, error_code)` method in case of parsing error
|
||||
- `named!` now handles thge alternative `named!(pub fun_name<OutputType>, ...)`
|
||||
|
||||
### Fixed
|
||||
- `filter!` now returns the whole input if the filter function never returned false
|
||||
- `take!` casts its argument as usize, so it can accepts any integer type now
|
||||
|
||||
## 0.3.5 - 2015-06-10
|
||||
|
||||
### Thanks
|
||||
- @cmr for some documentation fixes
|
||||
|
||||
### Added
|
||||
- `count_fixed!` returns a fixed array
|
||||
|
||||
### Fixed
|
||||
- `count!` is back to the previous behaviour, returning a `Vec` for sizes known at runtime
|
||||
|
||||
### Changed
|
||||
- functions and traits exported from `nom::util` are now directly in `nom::`
|
||||
|
||||
## 0.3.4 - 2015-06-09
|
||||
|
||||
### Thanks
|
||||
- @andrew-d for fixes on `cond!`
|
||||
- @keruspe for features in `chain!`
|
||||
|
||||
### Added
|
||||
- `chain!` can now have mutable fields
|
||||
|
||||
### Fixed
|
||||
- `cond!` had an infinite macro recursion
|
||||
|
||||
### Changed
|
||||
- `chain!` generates less code now. No apprent compilation time improvement
|
||||
|
||||
## 0.3.3 - 2015-06-09
|
||||
|
||||
### Thanks
|
||||
- @andrew-d for the little endian signed integer parsers
|
||||
- @keruspe for fixes on `count!`
|
||||
|
||||
### Added
|
||||
- `le_i8`, `le_i16`, `le_i32`, `le_i64`: little endian signed integer parsers
|
||||
|
||||
### Changed
|
||||
- the `alt!` parser compiles much faster, even with more than 8 branches
|
||||
- `count!` can now return a fixed size array instead of a growable vector
|
||||
|
||||
## 0.3.2 - 2015-05-31
|
||||
|
||||
### Thanks
|
||||
- @keruspe for the `take_str` parser and the function application combinator
|
||||
|
||||
### Added
|
||||
- `take_str!`: takes the specified number of bytes and return a UTF-8 string
|
||||
- `apply!`: do partial application on the parameters of a function
|
||||
|
||||
### Changed
|
||||
- `Needed::Size` now contains a `usize` instead of a `u32`
|
||||
|
||||
## 0.3.1 - 2015-05-21
|
||||
|
||||
### Thanks
|
||||
- @divarvel for the big endian signed integer parsers
|
||||
|
||||
### Added
|
||||
- `be_i8`, `be_i16`, `be_i32`, `be_i64`: big endian signed integer parsers
|
||||
- the `core` feature can be passed to cargo to build with `no_std`
|
||||
- colored hexdump can be generated from error chains
|
||||
|
||||
## 0.3.0 - 2015-05-07
|
||||
|
||||
### Thanks
|
||||
- @filipegoncalves for some documentation and the new eof parser
|
||||
- @CrimsonVoid for putting fully qualified types in the macros
|
||||
- @lu_zero for some documentation fixes
|
||||
|
||||
### Added
|
||||
- new error types that can contain an error code, an input slice, and a list of following errors
|
||||
- `error!` will cut backtracking and return directly from the parser, with a specified error code
|
||||
- `eof` parser, successful if there is no more input
|
||||
- specific error codes for the parsers provided by nom
|
||||
|
||||
### Changed
|
||||
- fully qualified types in macros. A lot of imports are not needed anymore
|
||||
|
||||
### Removed
|
||||
- `FlatMap`, `FlatpMapOpt` and `Functor` traits (replaced by `map!`, `map_opt!` and `map_res!`)
|
||||
|
||||
## 0.2.2 - 2015-04-12
|
||||
|
||||
### Thanks
|
||||
- @filipegoncalves and @thehydroimpulse for debugging an infinite loop in many0 and many1
|
||||
- @thehydroimpulse for suggesting public named parsers
|
||||
- @skade for removing the dependency on the collections gate
|
||||
|
||||
### Added
|
||||
- `named!` can now declare public functions like this: `named!(pub tst, tag!("abcd"));`
|
||||
- `pair!(X,Y)` returns a tuple `(x, y)`
|
||||
- `separated_pair!(X, sep, Y)` returns a tuple `(x, y)`
|
||||
- `preceded!(opening, X)` returns `x`
|
||||
- `terminated!(X, closing)` returns `x`
|
||||
- `delimited(opening, X, closing)` returns `x`
|
||||
- `separated_list(sep, X)` returns a `Vec<X>`
|
||||
- `separated_nonempty_list(sep, X)` returns a `Vec<X>` of at list one element
|
||||
|
||||
### Changed
|
||||
- `many0!` and `many1!` forbid parsers that do not consume input
|
||||
- `is_a!`, `is_not!`, `alpha`, `digit`, `space`, `multispace` will now return an error if they do not consume at least one byte
|
||||
|
||||
## 0.2.1 - 2015-04-04
|
||||
|
||||
### Thanks
|
||||
- @mtsr for catching the remaining debug println!
|
||||
- @jag426 who killed a lot of warnings
|
||||
- @skade for removing the dependency on the core feature gate
|
||||
|
||||
|
||||
### Added
|
||||
- little endian unsigned int parsers le_u8, le_u16, le_u32, le_u64
|
||||
- `count!` to apply a parser a specified number of times
|
||||
- `cond!` applies a parser if the condition is met
|
||||
- more parser development tools in `util::*`
|
||||
|
||||
### Fixed
|
||||
- in one case, `opt!` would not compile
|
||||
|
||||
### Removed
|
||||
- most of the feature gates are now removed. The only one still needed is `collections`
|
||||
|
||||
## 0.2.0 - 2015-03-24
|
||||
*works with `rustc 1.0.0-dev (81e2396c7 2015-03-19) (built 2015-03-19)`*
|
||||
|
||||
### Thanks
|
||||
- Ryman for the AsBytes implementation
|
||||
- jag426 and jaredly for documentation fixes
|
||||
- eternaleye on #rust IRC for his help on the new macro syntax
|
||||
|
||||
### Changed
|
||||
- the AsBytes trait improves readability, no more b"...", but "..." instead
|
||||
- Incomplete will now hold either Needed;;Unknown, or Needed::Size(u32). Matching on Incomplete without caring for the value is done with `Incomplete(_)`, but if more granularity is mandatory, `Needed` can be matched too
|
||||
- `alt!` can pass the result of the parser to a closure
|
||||
- the `take_*` macros changed behaviour, the default case is now not to consume the separator. The macros have been renamed as follows: `take_until!` -> `take_until_and_consume!`, `take_until_and_leave!` -> `take_until!`, `take_until_either_and_leave!` -> `take_until_either!`, `take_until_either!` -> `take_until_either_and_consume!`
|
||||
|
||||
### Added
|
||||
- `peek!` macro: matches the future input but does not consume it
|
||||
- `length_value!` macro: the first argument is a parser returning a `n` that can cast to usize, then applies the second parser `n` times. The macro has a variant with a third argument indicating the expected input size for the second parser
|
||||
- benchmarks are available at https://github.com/Geal/nom_benchmarks
|
||||
- more documentation
|
||||
- **Unnamed parser syntax**: warning, this is a breaking change. With this new syntax, the macro combinators do not generate functions anymore, they create blocks. That way, they can be nested, for better readability. The `named!` macro is provided to create functions from parsers. Please be aware that nesting parsers comes with a small cost of compilation time, negligible in most cases, but can quickly get to the minutes scale if not careful. If this happens, separate your parsers in multiple subfunctions.
|
||||
- `named!`, `closure!` and `call!` macros used to support the unnamed syntax
|
||||
- `map!`, `map_opt!` and `map_res!` to combine a parser with a normal function, transforming the input directly, or returning an `Option` or `Result`
|
||||
|
||||
### Fixed
|
||||
- `is_a!` is now working properly
|
||||
|
||||
### Removed
|
||||
- the `o!` macro does less than `chain!`, so it has been removed
|
||||
- the `fold0!` and `fold1!` macros were too complex and awkward to use, the `many*` combinators will be useful for most uses for now
|
||||
|
||||
## 0.1.6 - 2015-02-24
|
||||
### Changed
|
||||
- consumers must have an end method that will be called after parsing
|
||||
|
||||
### Added
|
||||
- big endian unsigned int and float parsers: be_u8, be_u16, be_u32, be_u64, be_f32, be_f64
|
||||
- producers can seek
|
||||
- function and macros documentation
|
||||
- README documentation
|
||||
### Fixed
|
||||
- lifetime declarations
|
||||
- tag! can return Incomplete
|
||||
|
||||
## 0.1.5 - 2015-02-17
|
||||
### Changed
|
||||
- traits were renamed: FlatMapper -> FlatMap, Mapper -> FlatMapOpt, Mapper2 -> Functor
|
||||
|
||||
### Fixed
|
||||
- woeks with rustc f1bb6c2f4
|
||||
|
||||
## 0.1.4 - 2015-02-17
|
||||
### Changed
|
||||
- the chaining macro can take optional arguments with '?'
|
||||
|
||||
## 0.1.3 - 2015-02-16
|
||||
### Changed
|
||||
- the chaining macro now takes the closure at the end of the argument list
|
||||
|
||||
## 0.1.2 - 2015-02-16
|
||||
### Added
|
||||
- flat_map implementation for <&[u8], &[u8]>
|
||||
- chaining macro
|
||||
- partial MP4 parser example
|
||||
|
||||
|
||||
## 0.1.1 - 2015-02-06
|
||||
### Fixed
|
||||
- closure syntax change
|
||||
|
||||
## Compare code
|
||||
|
||||
* [unreleased]: https://github.com/Geal/nom/compare/1.2.4...HEAD
|
||||
* [1.2.3]: https://github.com/Geal/nom/compare/1.2.3...1.2.4
|
||||
* [1.2.3]: https://github.com/Geal/nom/compare/1.2.2...1.2.3
|
||||
* [1.2.2]: https://github.com/Geal/nom/compare/1.2.1...1.2.2
|
||||
* [1.2.1]: https://github.com/Geal/nom/compare/1.2.0...1.2.1
|
||||
* [1.2.0]: https://github.com/Geal/nom/compare/1.1.0...1.2.0
|
||||
* [1.1.0]: https://github.com/Geal/nom/compare/1.0.1...1.1.0
|
||||
* [1.0.1]: https://github.com/Geal/nom/compare/1.0.0...1.0.1
|
||||
* [1.0.0]: https://github.com/Geal/nom/compare/0.5.0...1.0.0
|
||||
* [0.5.0]: https://github.com/geal/nom/compare/0.4.0...0.5.0
|
||||
* [0.4.0]: https://github.com/geal/nom/compare/0.3.11...0.4.0
|
||||
* [0.3.11]: https://github.com/geal/nom/compare/0.3.10...0.3.11
|
||||
* [0.3.10]: https://github.com/geal/nom/compare/0.3.9...0.3.10
|
||||
* [0.3.9]: https://github.com/geal/nom/compare/0.3.8...0.3.9
|
||||
* [0.3.8]: https://github.com/Geal/nom/compare/0.3.7...0.3.8
|
||||
* [0.3.7]: https://github.com/Geal/nom/compare/0.3.6...0.3.7
|
||||
* [0.3.6]: https://github.com/Geal/nom/compare/0.3.5...0.3.6
|
||||
* [0.3.5]: https://github.com/Geal/nom/compare/0.3.4...0.3.5
|
||||
* [0.3.4]: https://github.com/Geal/nom/compare/0.3.3...0.3.4
|
||||
* [0.3.3]: https://github.com/Geal/nom/compare/0.3.2...0.3.3
|
||||
* [0.3.2]: https://github.com/Geal/nom/compare/0.3.1...0.3.2
|
||||
* [0.3.1]: https://github.com/Geal/nom/compare/0.3.0...0.3.1
|
||||
* [0.3.0]: https://github.com/Geal/nom/compare/0.2.2...0.3.0
|
||||
* [0.2.2]: https://github.com/Geal/nom/compare/0.2.1...0.2.2
|
||||
* [0.2.1]: https://github.com/Geal/nom/compare/0.2.0...0.2.1
|
||||
* [0.2.0]: https://github.com/Geal/nom/compare/0.1.6...0.2.0
|
||||
* [0.1.6]: https://github.com/Geal/nom/compare/0.1.5...0.1.6
|
||||
* [0.1.5]: https://github.com/Geal/nom/compare/0.1.4...0.1.5
|
||||
* [0.1.4]: https://github.com/Geal/nom/compare/0.1.3...0.1.4
|
||||
* [0.1.3]: https://github.com/Geal/nom/compare/0.1.2...0.1.3
|
||||
* [0.1.2]: https://github.com/Geal/nom/compare/0.1.1...0.1.2
|
||||
* [0.1.1]: https://github.com/Geal/nom/compare/0.1.0...0.1.1
|
|
@ -1,38 +0,0 @@
|
|||
[package]
|
||||
|
||||
name = "nom"
|
||||
version = "1.2.4"
|
||||
authors = [ "contact@geoffroycouprie.com" ]
|
||||
description = "A byte-oriented, zero-copy, parser combinators library"
|
||||
license = "MIT"
|
||||
repository = "https://github.com/Geal/nom"
|
||||
readme = "README.md"
|
||||
documentation = "http://rust.unhandledexpression.com/nom/"
|
||||
keywords = ["parser", "parser-combinators", "parsing", "streaming", "bit"]
|
||||
|
||||
include = [
|
||||
"CHANGELOG.md",
|
||||
"LICENSE",
|
||||
".gitignore",
|
||||
".travis.yml",
|
||||
"Cargo.toml",
|
||||
"src/*.rs",
|
||||
"tests/*.rs"
|
||||
]
|
||||
|
||||
[features]
|
||||
core = []
|
||||
nightly = []
|
||||
default = ["stream"]
|
||||
regexp = ["regex"]
|
||||
regexp_macros = ["regexp", "lazy_static"]
|
||||
stream = []
|
||||
|
||||
[dependencies.regex]
|
||||
version = "^0.1.56"
|
||||
optional = true
|
||||
|
||||
[dependencies.lazy_static]
|
||||
version = "^0.2.1"
|
||||
optional = true
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
Copyright (c) 2015 Geoffroy Couprie
|
||||
|
||||
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.
|
|
@ -1,220 +0,0 @@
|
|||
//! Bit level parsers and combinators
|
||||
//!
|
||||
//! Bit parsing is handled by tweaking the input in most macros.
|
||||
//! In byte level parsing, the input is generally a `&[u8]` passed from combinator
|
||||
//! to combinator until the slices are manipulated.
|
||||
//!
|
||||
//! Bit parsers take a `(&[u8], usize)` as input. The first part of the tuple is an byte slice,
|
||||
//! the second part is a bit offset in the first byte of the slice.
|
||||
//!
|
||||
//! By passing a pair like this, we can leverage most of the combinators, and avoid
|
||||
//! transforming the whole slice to a vector of booleans. This should make it easy
|
||||
//! to see a byte slice as a bit stream, and parse code points of arbitrary bit length.
|
||||
|
||||
|
||||
/// `bits!( parser ) => ( &[u8], (&[u8], usize) -> IResult<(&[u8], usize), T> ) -> IResult<&[u8], T>`
|
||||
/// transforms its byte slice input into a bit stream for the underlying parsers
|
||||
///
|
||||
/// ```
|
||||
/// # #[macro_use] extern crate nom;
|
||||
/// # use nom::IResult::Done;
|
||||
/// # fn main() {
|
||||
/// named!( take_3_bits<u8>, bits!( take_bits!( u8, 3 ) ) );
|
||||
///
|
||||
/// let input = vec![0b10101010, 0b11110000, 0b00110011];
|
||||
/// let sl = &input[..];
|
||||
///
|
||||
/// assert_eq!(take_3_bits( sl ), Done(&sl[1..], 5) );
|
||||
/// # }
|
||||
#[macro_export]
|
||||
macro_rules! bits (
|
||||
($i:expr, $submac:ident!( $($args:tt)* )) => (
|
||||
bits_impl!($i, $submac!($($args)*));
|
||||
);
|
||||
($i:expr, $f:expr) => (
|
||||
bits_impl!($i, call!($f));
|
||||
);
|
||||
);
|
||||
|
||||
/// Internal parser, do not use directly
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! bits_impl (
|
||||
($i:expr, $submac:ident!( $($args:tt)* )) => (
|
||||
{
|
||||
let input = ($i, 0usize);
|
||||
match $submac!(input, $($args)*) {
|
||||
$crate::IResult::Error(e) => {
|
||||
let err = match e {
|
||||
$crate::Err::Code(k) | $crate::Err::Node(k, _) => $crate::Err::Code(k),
|
||||
$crate::Err::Position(k, (i,b)) | $crate::Err::NodePosition(k, (i,b), _) => {
|
||||
$crate::Err::Position(k, &i[b/8..])
|
||||
}
|
||||
};
|
||||
$crate::IResult::Error(err)
|
||||
}
|
||||
$crate::IResult::Incomplete($crate::Needed::Unknown) => $crate::IResult::Incomplete($crate::Needed::Unknown),
|
||||
$crate::IResult::Incomplete($crate::Needed::Size(i)) => {
|
||||
//println!("bits parser returned Needed::Size({})", i);
|
||||
$crate::IResult::Incomplete($crate::Needed::Size(i / 8 + 1))
|
||||
},
|
||||
$crate::IResult::Done((i, bit_index), o) => {
|
||||
let byte_index = bit_index / 8 + if bit_index % 8 == 0 { 0 } else { 1 } ;
|
||||
//println!("bit index=={} => byte index=={}", bit_index, byte_index);
|
||||
$crate::IResult::Done(&i[byte_index..], o)
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
/// `take_bits!(type, nb) => ( (&[T], usize), U, usize) -> IResult<(&[T], usize), U>`
|
||||
/// generates a parser consuming the specified number of bits.
|
||||
///
|
||||
/// ```
|
||||
/// # #[macro_use] extern crate nom;
|
||||
/// # use nom::IResult::Done;
|
||||
/// # fn main() {
|
||||
/// named!( take_pair<(u8, u8)>, bits!( pair!( take_bits!( u8, 3 ), take_bits!(u8, 5) ) ) );
|
||||
///
|
||||
/// let input = vec![0b10101010, 0b11110000, 0b00110011];
|
||||
/// let sl = &input[..];
|
||||
///
|
||||
/// assert_eq!(take_pair( sl ), Done(&sl[1..], (5, 10)) );
|
||||
/// assert_eq!(take_pair( &sl[1..] ), Done(&sl[2..], (7, 16)) );
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! take_bits (
|
||||
($i:expr, $t:ty, $count:expr) => (
|
||||
{
|
||||
use std::ops::Div;
|
||||
//println!("taking {} bits from {:?}", $count, $i);
|
||||
let (input, bit_offset) = $i;
|
||||
let res : $crate::IResult<(&[u8],usize), $t> = if $count == 0 {
|
||||
$crate::IResult::Done( (input, bit_offset), 0)
|
||||
} else {
|
||||
let cnt = ($count as usize + bit_offset).div(8);
|
||||
if input.len() * 8 < $count as usize + bit_offset {
|
||||
//println!("returning incomplete: {}", $count as usize + bit_offset);
|
||||
$crate::IResult::Incomplete($crate::Needed::Size($count as usize))
|
||||
} else {
|
||||
let mut acc:$t = 0;
|
||||
let mut offset: usize = bit_offset;
|
||||
let mut remaining: usize = $count;
|
||||
let mut end_offset: usize = 0;
|
||||
|
||||
for byte in input.iter().take(cnt + 1) {
|
||||
if remaining == 0 {
|
||||
break;
|
||||
}
|
||||
let val: $t = if offset == 0 {
|
||||
*byte as $t
|
||||
} else {
|
||||
((*byte << offset) as u8 >> offset) as $t
|
||||
};
|
||||
|
||||
if remaining < 8 - offset {
|
||||
acc += val >> (8 - offset - remaining);
|
||||
end_offset = remaining + offset;
|
||||
break;
|
||||
} else {
|
||||
acc += val << (remaining - (8 - offset));
|
||||
remaining -= 8 - offset;
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
$crate::IResult::Done( (&input[cnt..], end_offset) , acc)
|
||||
}
|
||||
};
|
||||
res
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
/// matches an integer pattern to a bitstream. The number of bits of the input to compare must be specified
|
||||
#[macro_export]
|
||||
macro_rules! tag_bits (
|
||||
($i:expr, $t:ty, $count:expr, $p: pat) => (
|
||||
{
|
||||
match take_bits!($i, $t, $count) {
|
||||
$crate::IResult::Incomplete(i) => $crate::IResult::Incomplete(i),
|
||||
$crate::IResult::Done(i, o) => {
|
||||
if let $p = o {
|
||||
let res: $crate::IResult<(&[u8],usize),$t> = $crate::IResult::Done(i, o);
|
||||
res
|
||||
} else {
|
||||
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TagBits, $i))
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TagBits, $i))
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use internal::{IResult,Needed,Err};
|
||||
use ErrorKind;
|
||||
|
||||
#[test]
|
||||
fn take_bits() {
|
||||
let input = vec![0b10101010, 0b11110000, 0b00110011];
|
||||
let sl = &input[..];
|
||||
|
||||
assert_eq!(take_bits!( (sl, 0), u8, 0 ), IResult::Done((sl, 0), 0));
|
||||
assert_eq!(take_bits!( (sl, 0), u8, 8 ), IResult::Done((&sl[1..], 0), 170));
|
||||
assert_eq!(take_bits!( (sl, 0), u8, 3 ), IResult::Done((&sl[0..], 3), 5));
|
||||
assert_eq!(take_bits!( (sl, 0), u8, 6 ), IResult::Done((&sl[0..], 6), 42));
|
||||
assert_eq!(take_bits!( (sl, 1), u8, 1 ), IResult::Done((&sl[0..], 2), 0));
|
||||
assert_eq!(take_bits!( (sl, 1), u8, 2 ), IResult::Done((&sl[0..], 3), 1));
|
||||
assert_eq!(take_bits!( (sl, 1), u8, 3 ), IResult::Done((&sl[0..], 4), 2));
|
||||
assert_eq!(take_bits!( (sl, 6), u8, 3 ), IResult::Done((&sl[1..], 1), 5));
|
||||
assert_eq!(take_bits!( (sl, 0), u16, 10 ), IResult::Done((&sl[1..], 2), 683));
|
||||
assert_eq!(take_bits!( (sl, 0), u16, 8 ), IResult::Done((&sl[1..], 0), 170));
|
||||
assert_eq!(take_bits!( (sl, 6), u16, 10 ), IResult::Done((&sl[2..], 0), 752));
|
||||
assert_eq!(take_bits!( (sl, 6), u16, 11 ), IResult::Done((&sl[2..], 1), 1504));
|
||||
assert_eq!(take_bits!( (sl, 0), u32, 20 ), IResult::Done((&sl[2..], 4), 700163));
|
||||
assert_eq!(take_bits!( (sl, 4), u32, 20 ), IResult::Done((&sl[3..], 0), 716851));
|
||||
assert_eq!(take_bits!( (sl, 4), u32, 22 ), IResult::Incomplete(Needed::Size(22)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tag_bits() {
|
||||
let input = vec![0b10101010, 0b11110000, 0b00110011];
|
||||
let sl = &input[..];
|
||||
|
||||
assert_eq!(tag_bits!( (sl, 0), u8, 3, 0b101), IResult::Done((&sl[0..], 3), 5));
|
||||
assert_eq!(tag_bits!( (sl, 0), u8, 4, 0b1010), IResult::Done((&sl[0..], 4), 10));
|
||||
}
|
||||
|
||||
named!(ch<(&[u8],usize),(u8,u8)>,
|
||||
chain!(
|
||||
tag_bits!(u8, 3, 0b101) ~
|
||||
x: take_bits!(u8, 4) ~
|
||||
y: take_bits!(u8, 5) ,
|
||||
|| { (x,y) }
|
||||
)
|
||||
);
|
||||
|
||||
#[test]
|
||||
fn chain_bits() {
|
||||
let input = vec![0b10101010, 0b11110000, 0b00110011];
|
||||
let sl = &input[..];
|
||||
assert_eq!(ch((&input[..],0)), IResult::Done((&sl[1..], 4), (5,15)));
|
||||
assert_eq!(ch((&input[..],4)), IResult::Done((&sl[2..], 0), (7,16)));
|
||||
assert_eq!(ch((&input[..1],0)), IResult::Incomplete(Needed::Size(12)));
|
||||
}
|
||||
|
||||
named!(ch_bytes<(u8,u8)>, bits!(ch));
|
||||
#[test]
|
||||
fn bits_to_bytes() {
|
||||
let input = vec![0b10101010, 0b11110000, 0b00110011];
|
||||
assert_eq!(ch_bytes(&input[..]), IResult::Done(&input[2..], (5,15)));
|
||||
assert_eq!(ch_bytes(&input[..1]), IResult::Incomplete(Needed::Size(2)));
|
||||
assert_eq!(ch_bytes(&input[1..]), IResult::Error(Err::Position(ErrorKind::TagBits, &input[1..])));
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,184 +0,0 @@
|
|||
/// Character level parsers
|
||||
|
||||
use internal::{IResult,Needed,Err};
|
||||
use util::ErrorKind;
|
||||
|
||||
/// matches one of the provided characters
|
||||
#[macro_export]
|
||||
macro_rules! one_of (
|
||||
($i:expr, $inp: expr) => (
|
||||
{
|
||||
if $i.is_empty() {
|
||||
$crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
|
||||
} else {
|
||||
#[inline(always)]
|
||||
fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
|
||||
b.as_bytes()
|
||||
}
|
||||
|
||||
let expected = $inp;
|
||||
let bytes = as_bytes(&expected);
|
||||
one_of_bytes!($i, bytes)
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! one_of_bytes (
|
||||
($i:expr, $bytes: expr) => (
|
||||
{
|
||||
if $i.is_empty() {
|
||||
$crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
|
||||
} else {
|
||||
let mut found = false;
|
||||
|
||||
for &i in $bytes {
|
||||
if i == $i[0] {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if found {
|
||||
$crate::IResult::Done(&$i[1..], $i[0] as char)
|
||||
} else {
|
||||
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::OneOf, $i))
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
/// matches anything but the provided characters
|
||||
#[macro_export]
|
||||
macro_rules! none_of (
|
||||
($i:expr, $inp: expr) => (
|
||||
{
|
||||
if $i.is_empty() {
|
||||
$crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
|
||||
} else {
|
||||
#[inline(always)]
|
||||
fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
|
||||
b.as_bytes()
|
||||
}
|
||||
|
||||
let expected = $inp;
|
||||
let bytes = as_bytes(&expected);
|
||||
none_of_bytes!($i, bytes)
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! none_of_bytes (
|
||||
($i:expr, $bytes: expr) => (
|
||||
{
|
||||
if $i.is_empty() {
|
||||
$crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
|
||||
} else {
|
||||
let mut found = false;
|
||||
|
||||
for &i in $bytes {
|
||||
if i == $i[0] {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
$crate::IResult::Done(&$i[1..], $i[0] as char)
|
||||
} else {
|
||||
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::NoneOf, $i))
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
/// matches one character: `char!(char) => &[u8] -> IResult<&[u8], char>
|
||||
#[macro_export]
|
||||
macro_rules! char (
|
||||
($i:expr, $c: expr) => (
|
||||
{
|
||||
if $i.is_empty() {
|
||||
let res: $crate::IResult<&[u8], char> = $crate::IResult::Incomplete($crate::Needed::Size(1));
|
||||
res
|
||||
} else {
|
||||
if $i[0] == $c as u8 {
|
||||
$crate::IResult::Done(&$i[1..], $i[0] as char)
|
||||
} else {
|
||||
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::Char, $i))
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
named!(pub newline<char>, char!('\n'));
|
||||
|
||||
pub fn crlf(input:&[u8]) -> IResult<&[u8], char> {
|
||||
if input.len() < 2 {
|
||||
IResult::Incomplete(Needed::Size(2))
|
||||
} else {
|
||||
if &input[0..2] == &b"\r\n"[..] {
|
||||
IResult::Done(&input[2..], '\n')
|
||||
} else {
|
||||
IResult::Error(Err::Position(ErrorKind::CrLf, input))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
named!(pub eol<char>, alt!(crlf | newline));
|
||||
named!(pub tab<char>, char!('\t'));
|
||||
|
||||
pub fn anychar(input:&[u8]) -> IResult<&[u8], char> {
|
||||
if input.is_empty() {
|
||||
IResult::Incomplete(Needed::Size(1))
|
||||
} else {
|
||||
IResult::Done(&input[1..], input[0] as char)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use internal::IResult::*;
|
||||
use internal::Err::*;
|
||||
use util::ErrorKind;
|
||||
|
||||
#[test]
|
||||
fn one_of() {
|
||||
named!(f<char>, one_of!("ab"));
|
||||
|
||||
let a = &b"abcd"[..];
|
||||
assert_eq!(f(a), Done(&b"bcd"[..], 'a'));
|
||||
|
||||
let b = &b"cde"[..];
|
||||
assert_eq!(f(b), Error(Position(ErrorKind::OneOf, b)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn none_of() {
|
||||
named!(f<char>, none_of!("ab"));
|
||||
|
||||
let a = &b"abcd"[..];
|
||||
assert_eq!(f(a), Error(Position(ErrorKind::NoneOf, a)));
|
||||
|
||||
let b = &b"cde"[..];
|
||||
assert_eq!(f(b), Done(&b"de"[..], 'c'));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn char() {
|
||||
named!(f<char>, char!('c'));
|
||||
|
||||
let a = &b"abcd"[..];
|
||||
assert_eq!(f(a), Error(Position(ErrorKind::Char, a)));
|
||||
|
||||
let b = &b"cde"[..];
|
||||
assert_eq!(f(b), Done(&b"de"[..], 'c'));
|
||||
}
|
||||
}
|
|
@ -1,347 +0,0 @@
|
|||
//! Basic types to build the parsers
|
||||
|
||||
use self::IResult::*;
|
||||
use self::Needed::*;
|
||||
use util::ErrorKind;
|
||||
|
||||
#[cfg(feature = "core")]
|
||||
use std::prelude::v1::*;
|
||||
use std::boxed::Box;
|
||||
|
||||
/// Contains the error that a parser can return
|
||||
///
|
||||
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
|
||||
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
|
||||
#[derive(Debug,PartialEq,Eq,Clone)]
|
||||
pub enum Err<P,E=u32>{
|
||||
/// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
|
||||
Code(ErrorKind<E>),
|
||||
/// An error code, and the next error
|
||||
Node(ErrorKind<E>, Box<Err<P,E>>),
|
||||
/// An error code, and the input position
|
||||
Position(ErrorKind<E>, P),
|
||||
/// An error code, the input position and the next error
|
||||
NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
|
||||
}
|
||||
|
||||
/// Contains information on needed data if a parser returned `Incomplete`
|
||||
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
|
||||
pub enum Needed {
|
||||
/// needs more data, but we do not know how much
|
||||
Unknown,
|
||||
/// contains the required data size
|
||||
Size(usize)
|
||||
}
|
||||
|
||||
impl Needed {
|
||||
pub fn is_known(&self) -> bool {
|
||||
*self != Unknown
|
||||
}
|
||||
|
||||
/// Maps a `Needed` to `Needed` by appling a function to a contained `Size` value.
|
||||
#[inline]
|
||||
pub fn map<F: FnOnce(usize) -> usize>(self, f: F) -> Needed {
|
||||
match self {
|
||||
Unknown => Unknown,
|
||||
Size(n) => Size(f(n)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Holds the result of parsing functions
|
||||
///
|
||||
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
|
||||
///
|
||||
#[derive(Debug,PartialEq,Eq,Clone)]
|
||||
pub enum IResult<I,O,E=u32> {
|
||||
/// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
|
||||
Done(I,O),
|
||||
/// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
|
||||
Error(Err<I,E>),
|
||||
/// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
|
||||
Incomplete(Needed)
|
||||
}
|
||||
|
||||
impl<I,O,E> IResult<I,O,E> {
|
||||
pub fn is_done(&self) -> bool {
|
||||
match *self {
|
||||
Done(_,_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_err(&self) -> bool {
|
||||
match *self {
|
||||
Error(_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_incomplete(&self) -> bool {
|
||||
match *self {
|
||||
Incomplete(_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps a `IResult<I, O, E>` to `IResult<I, N, E>` by appling a function
|
||||
/// to a contained `Done` value, leaving `Error` and `Incomplete` value
|
||||
/// untouched.
|
||||
#[inline]
|
||||
pub fn map<N, F: FnOnce(O) -> N>(self, f: F) -> IResult<I, N, E> {
|
||||
match self {
|
||||
Done(i, o) => Done(i, f(o)),
|
||||
Error(e) => Error(e),
|
||||
Incomplete(n) => Incomplete(n),
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps a `IResult<I, O, E>` to `IResult<I, O, E>` by appling a function
|
||||
/// to a contained `Incomplete` value, leaving `Done` and `Error` value
|
||||
/// untouched.
|
||||
#[inline]
|
||||
pub fn map_inc<F>(self, f: F) -> IResult<I, O, E>
|
||||
where F: FnOnce(Needed) -> Needed {
|
||||
match self {
|
||||
Error(e) => Error(e),
|
||||
Incomplete(n) => Incomplete(f(n)),
|
||||
Done(i, o) => Done(i, o),
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps a `IResult<I, O, E>` to `IResult<I, O, N>` by appling a function
|
||||
/// to a contained `Error` value, leaving `Done` and `Incomplete` value
|
||||
/// untouched.
|
||||
#[inline]
|
||||
pub fn map_err<N, F>(self, f: F) -> IResult<I, O, N>
|
||||
where F: FnOnce(Err<I, E>) -> Err<I, N> {
|
||||
match self {
|
||||
Error(e) => Error(f(e)),
|
||||
Incomplete(n) => Incomplete(n),
|
||||
Done(i, o) => Done(i, o),
|
||||
}
|
||||
}
|
||||
|
||||
/// Unwrap the contained `Done(I, O)` value, or panic if the `IResult` is not
|
||||
/// `Done`.
|
||||
pub fn unwrap(self) -> (I, O) {
|
||||
match self {
|
||||
Done(i, o) => (i, o),
|
||||
Incomplete(_) => panic!("unwrap() called on an IResult that is Incomplete"),
|
||||
Error(_) => panic!("unwrap() called on an IResult that is Error")
|
||||
}
|
||||
}
|
||||
|
||||
/// Unwrap the contained `Done(I, O)` value, or panic if the `IResult` is not
|
||||
/// `Done`.
|
||||
pub fn unwrap_inc(self) -> Needed {
|
||||
match self {
|
||||
Incomplete(n) => n,
|
||||
Done(_, _) => panic!("unwrap_inc() called on an IResult that is Done"),
|
||||
Error(_) => panic!("unwrap_inc() called on an IResult that is Error")
|
||||
}
|
||||
}
|
||||
|
||||
/// Unwrap the contained `Done(I, O)` value, or panic if the `IResult` is not
|
||||
/// `Done`.
|
||||
pub fn unwrap_err(self) -> Err<I, E> {
|
||||
match self {
|
||||
Error(e) => e,
|
||||
Done(_, _) => panic!("unwrap_err() called on an IResult that is Done"),
|
||||
Incomplete(_) => panic!("unwrap_err() called on an IResult that is Incomplete"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GetInput<I> {
|
||||
fn remaining_input(&self) -> Option<I>;
|
||||
}
|
||||
|
||||
pub trait GetOutput<O> {
|
||||
fn output(&self) -> Option<O>;
|
||||
}
|
||||
|
||||
impl<'a,I,O,E> GetInput<&'a[I]> for IResult<&'a[I],O,E> {
|
||||
fn remaining_input(&self) -> Option<&'a[I]> {
|
||||
match *self {
|
||||
Done(ref i,_) => Some(*i),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<O,E> GetInput<()> for IResult<(),O,E> {
|
||||
fn remaining_input(&self) -> Option<()> {
|
||||
match *self {
|
||||
Done((),_) => Some(()),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,O,E> GetInput<&'a str> for IResult<&'a str,O,E> {
|
||||
fn remaining_input(&self) -> Option<&'a str> {
|
||||
match *self {
|
||||
Done(ref i,_) => Some(*i),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,I,O,E> GetOutput<&'a[O]> for IResult<I,&'a[O],E> {
|
||||
fn output(&self) -> Option<&'a[O]> {
|
||||
match *self {
|
||||
Done(_, ref o) => Some(*o),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I,E> GetOutput<()> for IResult<I,(),E> {
|
||||
fn output(&self) -> Option<()> {
|
||||
match *self {
|
||||
Done(_,()) => Some(()),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a,I,E> GetOutput<&'a str> for IResult<I,&'a str,E> {
|
||||
fn output(&self) -> Option<&'a str> {
|
||||
match *self {
|
||||
Done(_,ref o) => Some(*o),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "core"))]
|
||||
use std::any::Any;
|
||||
#[cfg(not(feature = "core"))]
|
||||
use std::{error,fmt};
|
||||
#[cfg(not(feature = "core"))]
|
||||
use std::fmt::Debug;
|
||||
#[cfg(not(feature = "core"))]
|
||||
impl<P:Debug+Any,E:Debug+Any> error::Error for Err<P,E> {
|
||||
fn description(&self) -> &str {
|
||||
let kind = match *self {
|
||||
Err::Code(ref e) | Err::Node(ref e, _) | Err::Position(ref e, _) | Err::NodePosition(ref e, _, _) => e
|
||||
};
|
||||
kind.description()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "core"))]
|
||||
impl<P:fmt::Debug,E:fmt::Debug> fmt::Display for Err<P,E> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Err::Code(ref e) | Err::Node(ref e, _) => {
|
||||
write!(f, "{:?}", e)
|
||||
},
|
||||
Err::Position(ref e, ref p) | Err::NodePosition(ref e, ref p, _) => {
|
||||
write!(f, "{:?}:{:?}", p, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use util::ErrorKind;
|
||||
|
||||
const REST: [u8; 0] = [];
|
||||
const DONE: IResult<&'static [u8], u32> = IResult::Done(&REST, 5);
|
||||
const ERROR: IResult<&'static [u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
|
||||
const INCOMPLETE: IResult<&'static [u8], u32> = IResult::Incomplete(Needed::Unknown);
|
||||
|
||||
#[test]
|
||||
fn needed_map() {
|
||||
let unknown = Needed::Unknown;
|
||||
let size = Needed::Size(5);
|
||||
|
||||
assert_eq!(size.map(|x| x * 2), Needed::Size(10));
|
||||
assert_eq!(unknown.map(|x| x * 2), Needed::Unknown);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iresult_map() {
|
||||
assert_eq!(DONE.map(|x| x * 2), IResult::Done(&b""[..], 10));
|
||||
assert_eq!(ERROR.map(|x| x * 2), IResult::Error(Err::Code(ErrorKind::Tag)));
|
||||
assert_eq!(INCOMPLETE.map(|x| x * 2), IResult::Incomplete(Needed::Unknown));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iresult_map_inc() {
|
||||
let inc_unknown: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);
|
||||
let inc_size: IResult<&[u8], u32> = IResult::Incomplete(Needed::Size(5));
|
||||
|
||||
assert_eq!(DONE.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Done(&b""[..], 5));
|
||||
assert_eq!(ERROR.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Error(Err::Code(ErrorKind::Tag)));
|
||||
assert_eq!(inc_unknown.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Incomplete(Needed::Unknown));
|
||||
assert_eq!(inc_size.map_inc(|n| if let Needed::Size(i) = n {Needed::Size(i+1)} else {n}), IResult::Incomplete(Needed::Size(6)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iresult_map_err() {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
struct Error(u32);
|
||||
|
||||
let error_kind = Err::Code(ErrorKind::Custom(Error(5)));
|
||||
|
||||
assert_eq!(DONE.map_err(|_| error_kind.clone()), IResult::Done(&b""[..], 5));
|
||||
assert_eq!(ERROR.map_err(|x| {println!("err: {:?}", x); error_kind.clone()}), IResult::Error(error_kind.clone()));
|
||||
assert_eq!(INCOMPLETE.map_err(|x| {println!("err: {:?}", x); error_kind.clone()}), IResult::Incomplete(Needed::Unknown));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iresult_unwrap_on_done() {
|
||||
assert_eq!(DONE.unwrap(), (&b""[..], 5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn iresult_unwrap_on_err() {
|
||||
ERROR.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn iresult_unwrap_on_inc() {
|
||||
INCOMPLETE.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn iresult_unwrap_err_on_done() {
|
||||
DONE.unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iresult_unwrap_err_on_err() {
|
||||
assert_eq!(ERROR.unwrap_err(), Err::Code(ErrorKind::Tag));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn iresult_unwrap_err_on_inc() {
|
||||
INCOMPLETE.unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn iresult_unwrap_inc_on_done() {
|
||||
DONE.unwrap_inc();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn iresult_unwrap_inc_on_err() {
|
||||
ERROR.unwrap_inc();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iresult_unwrap_inc_on_inc() {
|
||||
assert_eq!(INCOMPLETE.unwrap_inc(), Needed::Unknown);
|
||||
}
|
||||
}
|
|
@ -1,151 +0,0 @@
|
|||
//! nom, eating data byte by byte
|
||||
//!
|
||||
//! nom is a parser combinator library with a focus on safe parsing,
|
||||
//! streaming patterns, and as much as possible zero copy.
|
||||
//!
|
||||
//! The code is available on [Github](https://github.com/Geal/nom)
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```
|
||||
//! #[macro_use]
|
||||
//! extern crate nom;
|
||||
//!
|
||||
//! use nom::{IResult,digit};
|
||||
//! use nom::IResult::*;
|
||||
//!
|
||||
//! // Parser definition
|
||||
//!
|
||||
//! use std::str;
|
||||
//! use std::str::FromStr;
|
||||
//!
|
||||
//! named!(parens<i64>, delimited!(
|
||||
//! char!('('),
|
||||
//! expr,
|
||||
//! char!(')')
|
||||
//! )
|
||||
//! );
|
||||
//!
|
||||
//! named!(i64_digit<i64>,
|
||||
//! map_res!(
|
||||
//! map_res!(
|
||||
//! digit,
|
||||
//! str::from_utf8
|
||||
//! ),
|
||||
//! FromStr::from_str
|
||||
//! )
|
||||
//! );
|
||||
//!
|
||||
//! // We transform an integer string into a i64
|
||||
//! // we look for a digit suite, and try to convert it.
|
||||
//! // if either str::from_utf8 or FromStr::from_str fail,
|
||||
//! // the parser will fail
|
||||
//! named!(factor<i64>,
|
||||
//! alt!(
|
||||
//! i64_digit
|
||||
//! | parens
|
||||
//! )
|
||||
//! );
|
||||
//!
|
||||
//! // we define acc as mutable to update its value whenever a new term is found
|
||||
//! named!(term <i64>,
|
||||
//! chain!(
|
||||
//! mut acc: factor ~
|
||||
//! many0!(
|
||||
//! alt!(
|
||||
//! tap!(mul: preceded!(tag!("*"), factor) => acc = acc * mul) |
|
||||
//! tap!(div: preceded!(tag!("/"), factor) => acc = acc / div)
|
||||
//! )
|
||||
//! ),
|
||||
//! || { return acc }
|
||||
//! )
|
||||
//! );
|
||||
//!
|
||||
//! named!(expr <i64>,
|
||||
//! chain!(
|
||||
//! mut acc: term ~
|
||||
//! many0!(
|
||||
//! alt!(
|
||||
//! tap!(add: preceded!(tag!("+"), term) => acc = acc + add) |
|
||||
//! tap!(sub: preceded!(tag!("-"), term) => acc = acc - sub)
|
||||
//! )
|
||||
//! ),
|
||||
//! || { return acc }
|
||||
//! )
|
||||
//! );
|
||||
//!
|
||||
//! fn main() {
|
||||
//! assert_eq!(expr(b"1+2"), IResult::Done(&b""[..], 3));
|
||||
//! assert_eq!(expr(b"12+6-4+3"), IResult::Done(&b""[..], 17));
|
||||
//! assert_eq!(expr(b"1+2*3+4"), IResult::Done(&b""[..], 11));
|
||||
//!
|
||||
//! assert_eq!(expr(b"(2)"), IResult::Done(&b""[..], 2));
|
||||
//! assert_eq!(expr(b"2*(3+4)"), IResult::Done(&b""[..], 14));
|
||||
//! assert_eq!(expr(b"2*2/(5-1)+3"), IResult::Done(&b""[..], 4));
|
||||
//! }
|
||||
//! ```
|
||||
#![cfg_attr(feature = "core", feature(no_std))]
|
||||
#![cfg_attr(feature = "core", feature(collections))]
|
||||
#![cfg_attr(feature = "core", no_std)]
|
||||
#![cfg_attr(feature = "nightly", feature(test))]
|
||||
#![cfg_attr(feature = "nightly", feature(const_fn))]
|
||||
|
||||
#[cfg(feature = "core")]
|
||||
extern crate collections;
|
||||
#[cfg(feature = "regexp")]
|
||||
extern crate regex;
|
||||
#[cfg(feature = "regexp_macros")]
|
||||
#[macro_use] extern crate lazy_static;
|
||||
#[cfg(feature = "nightly")]
|
||||
extern crate test;
|
||||
|
||||
#[cfg(feature = "core")]
|
||||
mod std {
|
||||
#[macro_use]
|
||||
pub use core::{fmt, iter, option, ops, slice, mem};
|
||||
pub use collections::{boxed, vec, string};
|
||||
pub mod prelude {
|
||||
pub use core::prelude as v1;
|
||||
}
|
||||
}
|
||||
|
||||
pub use self::util::*;
|
||||
pub use self::internal::*;
|
||||
pub use self::macros::*;
|
||||
pub use self::methods::*;
|
||||
pub use self::bytes::*;
|
||||
pub use self::bits::*;
|
||||
|
||||
pub use self::nom::*;
|
||||
pub use self::character::*;
|
||||
|
||||
#[cfg(feature = "regexp")]
|
||||
pub use self::regexp::*;
|
||||
|
||||
#[cfg(not(feature = "core"))]
|
||||
#[cfg(feature = "stream")]
|
||||
pub use self::stream::*;
|
||||
|
||||
#[cfg(not(feature = "core"))]
|
||||
pub use self::str::*;
|
||||
|
||||
#[macro_use] mod util;
|
||||
mod internal;
|
||||
#[macro_use] mod macros;
|
||||
#[macro_use] mod methods;
|
||||
#[macro_use] mod bytes;
|
||||
#[macro_use] mod bits;
|
||||
|
||||
#[macro_use] mod nom;
|
||||
#[macro_use] mod character;
|
||||
|
||||
#[cfg(feature = "regexp")]
|
||||
#[macro_use] mod regexp;
|
||||
|
||||
#[macro_use]
|
||||
#[cfg(not(feature = "core"))]
|
||||
#[cfg(feature = "stream")]
|
||||
mod stream;
|
||||
|
||||
#[cfg(not(feature = "core"))]
|
||||
mod str;
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,480 +0,0 @@
|
|||
//! Method macro combinators
|
||||
//!
|
||||
//! These macros make parsers as methods of structs
|
||||
//! and that can take methods of structs to call
|
||||
//! as parsers.
|
||||
//!
|
||||
//! There is a trick to make them easier to assemble,
|
||||
//! combinators are defined like this:
|
||||
//!
|
||||
//! ```ignore
|
||||
//! macro_rules! tag (
|
||||
//! ($i:expr, $inp: expr) => (
|
||||
//! {
|
||||
//! ...
|
||||
//! }
|
||||
//! );
|
||||
//! );
|
||||
//! ```
|
||||
//!
|
||||
//! But when used as methods in other combinators, are used
|
||||
//! like this:
|
||||
//!
|
||||
//! ```ignore
|
||||
//! method!(my_function<Parser<'a> >, self, tag!("abcd"));
|
||||
//! ```
|
||||
//!
|
||||
//! Internally, other combinators will rewrite
|
||||
//! that call to pass the input as second argument:
|
||||
//!
|
||||
//! ```ignore
|
||||
//! macro_rules! method (
|
||||
//! ($name:ident<$a:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
//! fn $name( $self_: $a, i: &[u8] ) -> $crate::IResult<&[u8], &[u8]> {
|
||||
//! $submac!(i, $($args)*)
|
||||
//! }
|
||||
//! );
|
||||
//! );
|
||||
//! ```
|
||||
//!
|
||||
//! The `method!` macro is similar to the `named!` macro in the macros module.
|
||||
//! While `named!` will create a parser function, `method!` will create a parser
|
||||
//! method on the struct it is defined in.
|
||||
//!
|
||||
//! Compared to the `named!` macro there are a few differences in how they are
|
||||
//! invoked. A `method!` invocation always has to have the type of `self`
|
||||
//! declared and it can't be a reference due to Rust's borrow lifetime
|
||||
//! restrictions:
|
||||
//! ```ignore
|
||||
//! // -`self`'s type-
|
||||
//! method!(method_name< Parser<'a> >, ...);
|
||||
//! ```
|
||||
//! `self`'s type always comes first.
|
||||
//! The next difference is you have to input the self struct. Due to Rust's
|
||||
//! macro hygiene the macro can't declare it on it's own.
|
||||
//! ```ignore
|
||||
//! // -self-
|
||||
//! method!(method_name<Parser<'a>, &'a str, &'a str>, self, ...);
|
||||
//! ```
|
||||
//! When making a parsing struct with parsing methods, due to the static borrow
|
||||
//! checker,calling any parsing methods on self (or any other parsing struct)
|
||||
//! will cause self to be moved for the rest of the method.To get around this
|
||||
//! restriction all self is moved into the called method and then the called
|
||||
//! method will return self to the caller.
|
||||
//!
|
||||
//! To call a method on self you need to use the `call_m!` macro. For example:
|
||||
//! ```ignore
|
||||
//! struct<'a> Parser<'a> {
|
||||
//! parsed: &'a str,
|
||||
//! }
|
||||
//! impl<'a> Parser<'a> {
|
||||
//! // Constructor omitted for brevity
|
||||
//! method!(take4<Parser<'a>, &'a str, &'a str>, self, take!(4));
|
||||
//! method!(caller<Parser<'a>, &'a str, &'a str>, self, call_m!(self.take4));
|
||||
//! }
|
||||
//! ```
|
||||
//! More complicated combinations still mostly look the same as their `named!`
|
||||
//! counterparts:
|
||||
//! ```ignore
|
||||
//! method!(pub simple_chain<&mut Parser<'a>, &'a str, &'a str>, self,
|
||||
//! chain!(
|
||||
//! call_m!(self.tag_abc) ~
|
||||
//! call_m!(self.tag_def) ~
|
||||
//! call_m!(self.tag_ghi) ~
|
||||
//! last: call_m!(self.simple_peek) ,
|
||||
//! ||{sb.parsed = last; last}
|
||||
//! )
|
||||
//! );
|
||||
//! ```
|
||||
//! The three additions to method definitions to remember are:
|
||||
//! 1. Specify `self`'s type
|
||||
//! 2. Pass `self` to the macro
|
||||
//! 4. Call parser methods using the `call_m!` macro.
|
||||
|
||||
/// Makes a method from a parser combination
|
||||
///
|
||||
/// The must be set up because the compiler needs
|
||||
/// the information
|
||||
///
|
||||
/// ```ignore
|
||||
/// method!(my_function<Parser<'a> >( &[u8] ) -> &[u8], tag!("abcd"));
|
||||
/// // first type parameter is `self`'s type, second is input, third is output
|
||||
/// method!(my_function<Parser<'a>, &[u8], &[u8]>, tag!("abcd"));
|
||||
/// //prefix them with 'pub' to make the methods public
|
||||
/// method!(pub my_function<Parser<'a>,&[u8], &[u8]>, tag!("abcd"));
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! method (
|
||||
// Non-public immutable self
|
||||
($name:ident<$a:ty>( $i:ty ) -> $o:ty, $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
($name:ident<$a:ty,$i:ty,$o:ty,$e:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i, $o, $e>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
($name:ident<$a:ty,$i:ty,$o:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
($name:ident<$a:ty,$o:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
fn $name<'a>( $self_: $a, i: &'a[u8] ) -> ($a, $crate::IResult<&'a [u8], $o, u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
($name:ident<$a:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
fn $name( $self_: $a, i: &[u8] ) -> ($a, $crate::IResult<&[u8], &[u8], u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
// Public immutable self
|
||||
(pub $name:ident<$a:ty>( $i:ty ) -> $o:ty, $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
pub fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
(pub $name:ident<$a:ty,$i:ty,$o:ty,$e:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
fn $name( $self_: $a, i: $i ) -> ($a, $crate::IResult<$i, $o, $e>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
(pub $name:ident<$a:ty,$i:ty,$o:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
pub fn $name( $self_: $a,i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
(pub $name:ident<$a:ty,$o:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
pub fn $name<'a>( $self_: $a, i: &'a[u8] ) -> ($a, $crate::IResult<&'a [u8], $o, u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
(pub $name:ident<$a:ty>, $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
pub fn $name( $self_: $a, i: &[u8] ) -> ($a, $crate::IResult<&[u8], &[u8], u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
// Non-public mutable self
|
||||
($name:ident<$a:ty>( $i:ty ) -> $o:ty, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
($name:ident<$a:ty,$i:ty,$o:ty,$e:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i, $o, $e>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
($name:ident<$a:ty,$i:ty,$o:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
($name:ident<$a:ty,$o:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
fn $name<'a>( mut $self_: $a, i: &'a[u8] ) -> ($a, $crate::IResult<&'a [u8], $o, u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
($name:ident<$a:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
fn $name( mut $self_: $a, i: &[u8] ) -> ($a, $crate::IResult<&[u8], &[u8], u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
// Public mutable self
|
||||
(pub $name:ident<$a:ty>( $i:ty ) -> $o:ty, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
pub fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
(pub $name:ident<$a:ty,$i:ty,$o:ty,$e:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
fn $name( mut $self_: $a, i: $i ) -> ($a, $crate::IResult<$i, $o, $e>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
(pub $name:ident<$a:ty,$i:ty,$o:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
pub fn $name( mut $self_: $a,i: $i ) -> ($a, $crate::IResult<$i,$o,u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
(pub $name:ident<$a:ty,$o:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
pub fn $name<'a>( mut $self_: $a, i: &'a[u8] ) -> ($a, $crate::IResult<&'a [u8], $o, u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
(pub $name:ident<$a:ty>, mut $self_:ident, $submac:ident!( $($args:tt)* )) => (
|
||||
pub fn $name( mut $self_: $a, i: &[u8] ) -> ($a, $crate::IResult<&[u8], &[u8], u32>) {
|
||||
let result = $submac!(i, $($args)*);
|
||||
($self_, result)
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
/// Used to called methods then move self back into self
|
||||
#[macro_export]
|
||||
macro_rules! call_m (
|
||||
($i:expr, $self_:ident.$method:ident) => (
|
||||
{
|
||||
let (tmp, res) = $self_.$method($i);
|
||||
$self_ = tmp;
|
||||
res
|
||||
}
|
||||
);
|
||||
($i:expr, $self_:ident.$method:ident, $($args:expr),* ) => (
|
||||
{
|
||||
let (tmp, res) = $self_.$method($i, $($args),*);
|
||||
$self_ = tmp;
|
||||
res
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
|
||||
/// emulate function currying for method calls on structs
|
||||
/// `apply!(self.my_function, arg1, arg2, ...)` becomes `self.my_function(input, arg1, arg2, ...)`
|
||||
///
|
||||
/// Supports up to 6 arguments
|
||||
#[macro_export]
|
||||
macro_rules! apply_m (
|
||||
($i:expr, $self_:ident.$method:ident, $($args:expr),* ) => ( { let (tmp, res) = $self_.$method( $i, $($args),* ); $self_ = tmp; res } );
|
||||
);
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use internal::IResult::*;
|
||||
|
||||
// reproduce the tag_s and take_s macros, because of module import order
|
||||
macro_rules! tag_s (
|
||||
($i:expr, $tag: expr) => (
|
||||
{
|
||||
let res: $crate::IResult<_,_> = if $tag.len() > $i.len() {
|
||||
$crate::IResult::Incomplete($crate::Needed::Size($tag.len()))
|
||||
//} else if &$i[0..$tag.len()] == $tag {
|
||||
} else if ($i).starts_with($tag) {
|
||||
$crate::IResult::Done(&$i[$tag.len()..], &$i[0..$tag.len()])
|
||||
} else {
|
||||
$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::TagStr, $i))
|
||||
};
|
||||
res
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
macro_rules! take_s (
|
||||
($i:expr, $count:expr) => (
|
||||
{
|
||||
let cnt = $count as usize;
|
||||
let res: $crate::IResult<_,_> = if $i.chars().count() < cnt {
|
||||
$crate::IResult::Incomplete($crate::Needed::Size(cnt))
|
||||
} else {
|
||||
let mut offset = $i.len();
|
||||
let mut count = 0;
|
||||
for (o, _) in $i.char_indices() {
|
||||
if count == cnt {
|
||||
offset = o;
|
||||
break;
|
||||
}
|
||||
count += 1;
|
||||
}
|
||||
$crate::IResult::Done(&$i[offset..], &$i[..offset])
|
||||
};
|
||||
res
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
struct Parser<'a> {
|
||||
bcd: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
pub fn new() -> Parser<'a> {
|
||||
Parser{bcd: ""}
|
||||
}
|
||||
|
||||
method!(tag_abc<Parser<'a>, &'a str, &'a str>, self, tag_s!("áβç"));
|
||||
method!(tag_bcd<Parser<'a> >(&'a str) -> &'a str, self, tag_s!("βçδ"));
|
||||
method!(pub tag_hij<Parser<'a> >(&'a str) -> &'a str, self, tag_s!("λïJ"));
|
||||
method!(pub tag_ijk<Parser<'a>, &'a str, &'a str>, self, tag_s!("ïJƙ"));
|
||||
method!(take3<Parser<'a>, &'a str, &'a str>, self, take_s!(3));
|
||||
method!(pub simple_call<Parser<'a>, &'a str, &'a str>, mut self,
|
||||
call_m!(self.tag_abc)
|
||||
);
|
||||
method!(pub simple_peek<Parser<'a>, &'a str, &'a str>, mut self,
|
||||
peek!(call_m!(self.take3))
|
||||
);
|
||||
method!(pub simple_chain<Parser<'a>, &'a str, &'a str>, mut self,
|
||||
chain!(
|
||||
bcd: call_m!(self.tag_bcd) ~
|
||||
last: call_m!(self.simple_peek) ,
|
||||
||{self.bcd = bcd; last}
|
||||
)
|
||||
);
|
||||
fn tag_stuff(mut self: Parser<'a>, input: &'a str, something: &'a str) -> (Parser<'a>, ::IResult<&'a str, &'a str>) {
|
||||
self.bcd = something;
|
||||
let(tmp, res) = self.tag_abc(input);
|
||||
self = tmp;
|
||||
(self, res)
|
||||
}
|
||||
method!(use_apply<Parser<'a>, &'a str, &'a str>, mut self, apply_m!(self.tag_stuff, "βçδ"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_method_call_abc() {
|
||||
let p = Parser::new();
|
||||
let input: &str = "áβçδèƒϱλïJƙ";
|
||||
let consumed: &str = "áβç";
|
||||
let leftover: &str = "δèƒϱλïJƙ";
|
||||
let(_, res) = p.tag_abc(input);
|
||||
match res {
|
||||
Done(extra, output) => { assert!(extra == leftover, "`Parser.tag_abc` consumed leftover input. leftover: {}", extra);
|
||||
assert!(output == consumed, "`Parser.tag_abc` doesnt return the string it consumed \
|
||||
on success. Expected `{}`, got `{}`.", consumed, output);
|
||||
},
|
||||
other => panic!("`Parser.tag_abc` didn't succeed when it should have. \
|
||||
Got `{:?}`.", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_method_call_bcd() {
|
||||
let p = Parser::new();
|
||||
let input: &str = "βçδèƒϱλïJƙ";
|
||||
let consumed: &str = "βçδ";
|
||||
let leftover: &str = "èƒϱλïJƙ";
|
||||
let(_, res) = p.tag_bcd(input);
|
||||
match res {
|
||||
Done(extra, output) => { assert!(extra == leftover, "`Parser.tag_bcd` consumed leftover input. leftover: {}", extra);
|
||||
assert!(output == consumed, "`Parser.tag_bcd` doesn't return the string it consumed \
|
||||
on success. Expected `{}`, got `{}`.", consumed, output);
|
||||
},
|
||||
other => panic!("`Parser.tag_bcd` didn't succeed when it should have. \
|
||||
Got `{:?}`.", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_method_call_hij() {
|
||||
let p = Parser::new();
|
||||
let input: &str = "λïJƙℓ₥ñôƥ9řƨ";
|
||||
let consumed: &str = "λïJ";
|
||||
let leftover: &str = "ƙℓ₥ñôƥ9řƨ";
|
||||
let(_, res) = p.tag_hij(input);
|
||||
match res {
|
||||
Done(extra, output) => { assert!(extra == leftover, "`Parser.tag_hij` consumed leftover input. leftover: {}", extra);
|
||||
assert!(output == consumed, "`Parser.tag_hij` doesn't return the string it consumed \
|
||||
on success. Expected `{}`, got `{}`.", consumed, output);
|
||||
},
|
||||
other => panic!("`Parser.tag_hij` didn't succeed when it should have. \
|
||||
Got `{:?}`.", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_method_call_ijk() {
|
||||
let p = Parser::new();
|
||||
let input: &str = "ïJƙℓ₥ñôƥ9řƨ";
|
||||
let consumed: &str = "ïJƙ";
|
||||
let leftover: &str = "ℓ₥ñôƥ9řƨ";
|
||||
let(_, res) = p.tag_ijk(input);
|
||||
match res {
|
||||
Done(extra, output) => { assert!(extra == leftover, "`Parser.tag_ijk` consumed leftover input. leftover: {}", extra);
|
||||
assert!(output == consumed, "`Parser.tag_ijk` doesn't return the string it consumed \
|
||||
on success. Expected `{}`, got `{}`.", consumed, output);
|
||||
},
|
||||
other => panic!("`Parser.tag_ijk` didn't succeed when it should have. \
|
||||
Got `{:?}`.", other),
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn test_method_simple_call() {
|
||||
let p = Parser::new();
|
||||
let input: &str = "áβçδèƒϱλïJƙ";
|
||||
let consumed: &str = "áβç";
|
||||
let leftover: &str = "δèƒϱλïJƙ";
|
||||
let(_, res) = p.simple_call(input);
|
||||
match res {
|
||||
Done(extra, output) => { assert!(extra == leftover, "`Parser.simple_call` consumed leftover input. leftover: {}", extra);
|
||||
assert!(output == consumed, "`Parser.simple_call` doesn't return the string it consumed \
|
||||
on success. Expected `{}`, got `{}`.", consumed, output);
|
||||
},
|
||||
other => panic!("`Parser.simple_call` didn't succeed when it should have. \
|
||||
Got `{:?}`.", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_apply_m() {
|
||||
let mut p = Parser::new();
|
||||
let input: &str = "áβçδèƒϱλïJƙ";
|
||||
let consumed: &str = "áβç";
|
||||
let leftover: &str = "δèƒϱλïJƙ";
|
||||
let(tmp, res) = p.use_apply(input);
|
||||
p = tmp;
|
||||
match res {
|
||||
Done(extra, output) => { assert!(extra == leftover, "`Parser.use_apply` consumed leftover input. leftover: {}", extra);
|
||||
assert!(output == consumed, "`Parser.use_apply` doesn't return the string it was supposed to \
|
||||
on success. Expected `{}`, got `{}`.", leftover, output);
|
||||
assert!(p.bcd == "βçδ", "Parser.use_apply didn't modify the parser field correctly: {}", p.bcd);
|
||||
},
|
||||
other => panic!("`Parser.use_apply` didn't succeed when it should have. \
|
||||
Got `{:?}`.", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_method_call_peek() {
|
||||
let p = Parser::new();
|
||||
let input: &str = "ж¥ƺáβçδèƒϱλïJƙ";
|
||||
let consumed: &str = "ж¥ƺ";
|
||||
let(_, res) = p.simple_peek(input);
|
||||
match res {
|
||||
Done(extra, output) => { assert!(extra == input, "`Parser.simple_peek` consumed leftover input. leftover: {}", extra);
|
||||
assert!(output == consumed, "`Parser.simple_peek` doesn't return the string it consumed \
|
||||
on success. Expected `{}`, got `{}`.", consumed, output);
|
||||
},
|
||||
other => panic!("`Parser.simple_peek` didn't succeed when it should have. \
|
||||
Got `{:?}`.", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_method_call_chain() {
|
||||
let mut p = Parser::new();
|
||||
let input : &str = "βçδδèƒϱλïJƙℓ";
|
||||
let leftover : &str = "δèƒϱλïJƙℓ";
|
||||
let output : &str = "늟";
|
||||
let(tmp, res) = p.simple_chain(input);
|
||||
p = tmp;
|
||||
match res {
|
||||
Done(extra, out) => { assert!(extra == leftover, "`Parser.simple_chain` consumed leftover input. leftover: {}", extra);
|
||||
assert!(out == output, "`Parser.simple_chain` doesn't return the string it was supposed to \
|
||||
on success. Expected `{}`, got `{}`.", output, out);
|
||||
assert!(p.bcd == "βçδ", "Parser.simple_chain didn't modify the parser field correctly: {}", p.bcd);
|
||||
},
|
||||
other => panic!("`Parser.simple_chain` didn't succeed when it should have. \
|
||||
Got `{:?}`.", other),
|
||||
}
|
||||
}
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче